Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package wtmpdb for openSUSE:Factory checked in at 2026-08-01 18:29:14 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/wtmpdb (Old) and /work/SRC/openSUSE:Factory/.wtmpdb.new.16738 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "wtmpdb" Sat Aug 1 18:29:14 2026 rev:26 rq:1368614 version:0.76.0+git20260730.89c0861 Changes: -------- --- /work/SRC/openSUSE:Factory/wtmpdb/wtmpdb.changes 2025-12-02 13:19:39.173585254 +0100 +++ /work/SRC/openSUSE:Factory/.wtmpdb.new.16738/wtmpdb.changes 2026-08-01 18:30:09.437461640 +0200 @@ -1,0 +2,13 @@ +Thu Jul 30 13:05:50 UTC 2026 - Thorsten Kukuk <[email protected]> + +- Update to version 0.76.0+git20260730.89c0861: + * Release version 0.76.0 + * CI: get rid of obsolete actions + * Use _cleanup_, adjust formating + * rotate: keep open entries after last boot + * wtmpdb: use different variable for (const) char * + * Update mkdir_p to fix error code for last call + * ignore absence of systemd + * ignore absense of dbus + +------------------------------------------------------------------- Old: ---- wtmpdb-0.75.0+git20251130.0d8fe7a.tar.xz New: ---- wtmpdb-0.76.0+git20260730.89c0861.tar.xz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ wtmpdb.spec ++++++ --- /var/tmp/diff_new_pack.djjzR2/_old 2026-08-01 18:30:10.153486013 +0200 +++ /var/tmp/diff_new_pack.djjzR2/_new 2026-08-01 18:30:10.157486148 +0200 @@ -1,7 +1,7 @@ # # spec file for package wtmpdb # -# Copyright (c) 2025 SUSE LLC and contributors +# Copyright (c) 2026 SUSE LLC and contributors # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -18,7 +18,7 @@ %define lname libwtmpdb0 Name: wtmpdb -Version: 0.75.0+git20251130.0d8fe7a +Version: 0.76.0+git20260730.89c0861 Release: 0 Summary: Database for recording the last logged in users and system reboots License: BSD-2-Clause ++++++ _service ++++++ --- /var/tmp/diff_new_pack.djjzR2/_old 2026-08-01 18:30:10.201487646 +0200 +++ /var/tmp/diff_new_pack.djjzR2/_new 2026-08-01 18:30:10.209487919 +0200 @@ -5,7 +5,8 @@ <param name="changesgenerate">enable</param> <param name="filename">wtmpdb</param> <param name="revision">main</param> - <param name="versionformat">0.75.0+git%cd.%h</param> + <param name="versionformat">@PARENT_TAG@+git%cd.%h</param> + <param name="versionrewrite-pattern">v(.*?)(\+git0)?$</param> </service> <service mode="manual" name="recompress"> <param name="file">*.tar</param> ++++++ _servicedata ++++++ --- /var/tmp/diff_new_pack.djjzR2/_old 2026-08-01 18:30:10.233488736 +0200 +++ /var/tmp/diff_new_pack.djjzR2/_new 2026-08-01 18:30:10.237488871 +0200 @@ -4,6 +4,6 @@ </service> <service name="tar_scm"> <param name="url">https://github.com/thkukuk/wtmpdb.git</param> - <param name="changesrevision">0d8fe7a1803a71e747ccf172e9c6c16af0ce6688</param></service></servicedata> + <param name="changesrevision">89c0861f74e576c5ad0ec9f5302aa635a4e50dc6</param></service></servicedata> (No newline at EOF) ++++++ wtmpdb-0.75.0+git20251130.0d8fe7a.tar.xz -> wtmpdb-0.76.0+git20260730.89c0861.tar.xz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/wtmpdb-0.75.0+git20251130.0d8fe7a/.github/workflows/ci-opensuse.yml new/wtmpdb-0.76.0+git20260730.89c0861/.github/workflows/ci-opensuse.yml --- old/wtmpdb-0.75.0+git20251130.0d8fe7a/.github/workflows/ci-opensuse.yml 2025-11-30 17:20:54.000000000 +0100 +++ new/wtmpdb-0.76.0+git20260730.89c0861/.github/workflows/ci-opensuse.yml 2026-07-30 14:48:03.000000000 +0200 @@ -8,7 +8,7 @@ container: registry.opensuse.org/opensuse/tumbleweed:latest steps: - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@v7 - name: Install devel packages run: | diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/wtmpdb-0.75.0+git20251130.0d8fe7a/.github/workflows/meson-sanitizer.yml new/wtmpdb-0.76.0+git20260730.89c0861/.github/workflows/meson-sanitizer.yml --- old/wtmpdb-0.75.0+git20251130.0d8fe7a/.github/workflows/meson-sanitizer.yml 2025-11-30 17:20:54.000000000 +0100 +++ new/wtmpdb-0.76.0+git20260730.89c0861/.github/workflows/meson-sanitizer.yml 2026-07-30 14:48:03.000000000 +0200 @@ -7,20 +7,14 @@ runs-on: ubuntu-latest steps: - - name: Install pam-devel - run: sudo apt-get install libpam0g-dev libsqlite3-dev - - uses: actions/checkout@v3 - - uses: BSFishy/[email protected] - with: - action: build - directory: build - setup-options: -Db_sanitize=address,undefined - options: --verbose - meson-version: 0.61.4 - - uses: BSFishy/[email protected] - with: - action: test - directory: build - setup-options: -Db_sanitize=address,undefined - options: --verbose - meson-version: 0.61.4 + - name: Update package data + run: sudo apt update + - name: Install devel packages + run: sudo apt-get install libpam0g-dev libsqlite3-dev meson ninja-build + - uses: actions/checkout@v7 + - name: Setup + run: meson setup build -Db_sanitize=address,undefined + - name: Build + run: meson compile -C build --verbose + - name: Test + run: meson test -C build --verbose diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/wtmpdb-0.75.0+git20251130.0d8fe7a/.github/workflows/meson.yml new/wtmpdb-0.76.0+git20260730.89c0861/.github/workflows/meson.yml --- old/wtmpdb-0.75.0+git20251130.0d8fe7a/.github/workflows/meson.yml 2025-11-30 17:20:54.000000000 +0100 +++ new/wtmpdb-0.76.0+git20260730.89c0861/.github/workflows/meson.yml 2026-07-30 14:48:03.000000000 +0200 @@ -7,16 +7,14 @@ runs-on: ubuntu-latest steps: - - name: Install pam-devel - run: sudo apt-get install libpam0g-dev libsqlite3-dev - - uses: actions/checkout@v3 - - uses: BSFishy/[email protected] - with: - action: build - options: --verbose - meson-version: 0.61.4 - - uses: BSFishy/[email protected] - with: - action: test - options: --verbose - meson-version: 0.61.4 + - name: Update package data + run: sudo apt update + - name: Install devel packages + run: sudo apt-get install libpam0g-dev libsqlite3-dev meson ninja-build + - uses: actions/checkout@v7 + - name: Setup + run: meson setup build + - name: Build + run: meson compile -C build --verbose + - name: Test + run: meson test -C build --verbose diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/wtmpdb-0.75.0+git20251130.0d8fe7a/NEWS new/wtmpdb-0.76.0+git20260730.89c0861/NEWS --- old/wtmpdb-0.75.0+git20251130.0d8fe7a/NEWS 2025-11-30 17:20:54.000000000 +0100 +++ new/wtmpdb-0.76.0+git20260730.89c0861/NEWS 2026-07-30 14:48:03.000000000 +0200 @@ -1,4 +1,5 @@ -Version 0.7X.0 +Version 0.76.0 +* Rotate: keep open entries since last boot * Fix last --present option * last -x: apply --since and --until to split entries * last -x: show shutdown entries before reboot ones diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/wtmpdb-0.75.0+git20251130.0d8fe7a/lib/basics.h new/wtmpdb-0.76.0+git20260730.89c0861/lib/basics.h --- old/wtmpdb-0.75.0+git20251130.0d8fe7a/lib/basics.h 2025-11-30 17:20:54.000000000 +0100 +++ new/wtmpdb-0.76.0+git20260730.89c0861/lib/basics.h 2026-07-30 14:48:03.000000000 +0200 @@ -2,7 +2,6 @@ #pragma once -#define _cleanup_(x) __attribute__((__cleanup__(x))) #define _unused_(x) x __attribute__((unused)) #define mfree(memory) \ @@ -15,3 +14,6 @@ *(void**)p = mfree(*(void**) p); } +#define _cleanup_(x) __attribute__((__cleanup__(x))) +#define _cleanup_free_ _cleanup_(freep) + diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/wtmpdb-0.75.0+git20251130.0d8fe7a/lib/mkdir_p.c new/wtmpdb-0.76.0+git20260730.89c0861/lib/mkdir_p.c --- old/wtmpdb-0.75.0+git20251130.0d8fe7a/lib/mkdir_p.c 2025-11-30 17:20:54.000000000 +0100 +++ new/wtmpdb-0.76.0+git20260730.89c0861/lib/mkdir_p.c 2026-07-30 14:48:03.000000000 +0200 @@ -1,29 +1,4 @@ -/* SPDX-License-Identifier: BSD-2-Clause - - Copyright (c) 2024, Thorsten Kukuk <[email protected]> - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. -*/ +// SPDX-License-Identifier: BSD-2-Clause #include <errno.h> #include <stddef.h> @@ -72,6 +47,9 @@ if (r < 0) return r; - return mkdir(path, mode); + if (mkdir(path, mode) == -1) + return -errno; + + return 0; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/wtmpdb-0.75.0+git20251130.0d8fe7a/lib/sqlite.c new/wtmpdb-0.76.0+git20260730.89c0861/lib/sqlite.c --- old/wtmpdb-0.75.0+git20251130.0d8fe7a/lib/sqlite.c 2025-11-30 17:20:54.000000000 +0100 +++ new/wtmpdb-0.76.0+git20260730.89c0861/lib/sqlite.c 2026-07-30 14:48:03.000000000 +0200 @@ -38,6 +38,7 @@ #include <sys/stat.h> #include <sqlite3.h> +#include "basics.h" #include "wtmpdb.h" #include "sqlite.h" #include "mkdir_p.h" @@ -64,17 +65,17 @@ /* Creates the table if it does not exist. * Returns 0 on success, -1 on failure. */ static int64_t -create_table (sqlite3 *db, char **error) +create_table(sqlite3 *db, char **error) { char *err_msg = NULL; char *sql_table = "CREATE TABLE IF NOT EXISTS wtmp(ID INTEGER PRIMARY KEY, Type INTEGER, User TEXT NOT NULL, Login INTEGER, Logout INTEGER, TTY TEXT, RemoteHost TEXT, Service TEXT) STRICT;"; - if (sqlite3_exec (db, sql_table, 0, 0, &err_msg) != SQLITE_OK) + if (sqlite3_exec(db, sql_table, 0, 0, &err_msg) != SQLITE_OK) { if (error) - if (asprintf (error, "SQL error creating table: %s", err_msg) < 0) - *error = strdup ("create_table: Out of memory"); - sqlite3_free (err_msg); + if (asprintf(error, "SQL error creating table: %s", err_msg) < 0) + *error = strdup("create_table: Out of memory"); + sqlite3_free(err_msg); return -1; } @@ -82,16 +83,16 @@ } static int -open_database_ro (const char *path, sqlite3 **db, char **error) +open_database_ro(const char *path, sqlite3 **db, char **error) { struct stat statbuf; int empty_file; int r; empty_file = stat(path, &statbuf) == 0 && statbuf.st_size == 0; - r = sqlite3_open_v2 (path, db, empty_file ? - SQLITE_OPEN_READWRITE | SQLITE_OPEN_MEMORY : - SQLITE_OPEN_READONLY, NULL); + r = sqlite3_open_v2(path, db, empty_file ? + SQLITE_OPEN_READWRITE | SQLITE_OPEN_MEMORY : + SQLITE_OPEN_READONLY, NULL); if (r != SQLITE_OK) { if (error) @@ -106,13 +107,13 @@ sqlite3_busy_timeout(*db, TIMEOUT); if (empty_file) - r = create_table (*db, error); + r = create_table(*db, error); return r == SQLITE_OK ? 0 : -1; } static int -open_database_rw (const char *path, sqlite3 **db, char **error) +open_database_rw(const char *path, sqlite3 **db, char **error) { int r; @@ -124,120 +125,120 @@ mode_t old_umask = umask(0077); #endif - r = sqlite3_open (path, db); + r = sqlite3_open(path, db); #if WITH_WTMPDBD - umask (old_umask); + umask(old_umask); #endif if (r != SQLITE_OK) { if (error) - if (asprintf (error, "Cannot create/open database (%s): %s", - path, sqlite3_errmsg (*db)) < 0) - *error = strdup ("open_database_rw: Out of memory"); + if (asprintf(error, "Cannot create/open database (%s): %s", + path, sqlite3_errmsg(*db)) < 0) + *error = strdup("open_database_rw: Out of memory"); - sqlite3_close (*db); + sqlite3_close(*db); *db = NULL; return -r; } sqlite3_busy_timeout(*db, TIMEOUT); - r = create_table (*db, error); + r = create_table(*db, error); return r == SQLITE_OK ? 0 : -1; } /* Add a new entry. Returns ID (>=0) on success, -1 on failure. */ static int64_t -add_entry (sqlite3 *db, int type, const char *user, - uint64_t usec_login, const char *tty, const char *rhost, - const char *service, char **error) +add_entry(sqlite3 *db, int type, const char *user, + uint64_t usec_login, const char *tty, const char *rhost, + const char *service, char **error) { sqlite3_stmt *res; char *sql_insert = "INSERT INTO wtmp (Type,User,Login,TTY,RemoteHost,Service) VALUES(?,?,?,?,?,?);"; - if (sqlite3_prepare_v2 (db, sql_insert, -1, &res, 0) != SQLITE_OK) + if (sqlite3_prepare_v2(db, sql_insert, -1, &res, 0) != SQLITE_OK) { if (error) - if (asprintf (error, "Failed to prepare statement (add_entry): %s", - sqlite3_errmsg (db)) < 0) - *error = strdup ("add_entry: Out of memory"); + if (asprintf(error, "Failed to prepare statement (add_entry): %s", + sqlite3_errmsg(db)) < 0) + *error = strdup("add_entry: Out of memory"); return -1; } - if (sqlite3_bind_int (res, 1, type) != SQLITE_OK) + if (sqlite3_bind_int(res, 1, type) != SQLITE_OK) { if (error) - if (asprintf (error, "Failed to create add statement for 'type': %s", - sqlite3_errmsg (db)) < 0) + if (asprintf(error, "Failed to create add statement for 'type': %s", + sqlite3_errmsg(db)) < 0) *error = strdup("add_entry: Out of memory"); sqlite3_finalize(res); return -1; } - if (sqlite3_bind_text (res, 2, user, -1, SQLITE_STATIC) != SQLITE_OK) + if (sqlite3_bind_text(res, 2, user, -1, SQLITE_STATIC) != SQLITE_OK) { if (error) - if (asprintf (error, "Failed to create add statement for 'user': %s", - sqlite3_errmsg (db)) < 0) - *error = strdup ("add_entry: Out of memory"); + if (asprintf(error, "Failed to create add statement for 'user': %s", + sqlite3_errmsg(db)) < 0) + *error = strdup("add_entry: Out of memory"); - sqlite3_finalize (res); + sqlite3_finalize(res); return -1; } - if (sqlite3_bind_int64 (res, 3, usec_login) != SQLITE_OK) + if (sqlite3_bind_int64(res, 3, usec_login) != SQLITE_OK) { if (error) - if (asprintf (error, "Failed to create add statement for 'login' time (add_entry): %s", - sqlite3_errmsg (db)) < 0) + if (asprintf(error, "Failed to create add statement for 'login' time (add_entry): %s", + sqlite3_errmsg(db)) < 0) *error = strdup("add_entry: Out of memory"); sqlite3_finalize(res); return -1; } - if (sqlite3_bind_text (res, 4, tty, -1, SQLITE_STATIC) != SQLITE_OK) + if (sqlite3_bind_text(res, 4, tty, -1, SQLITE_STATIC) != SQLITE_OK) { if (error) - if (asprintf (error, "Failed to create add statement for 'tty': %s", - sqlite3_errmsg (db)) < 0) + if (asprintf(error, "Failed to create add statement for 'tty': %s", + sqlite3_errmsg(db)) < 0) *error = strdup("add_entry: Out of memory"); sqlite3_finalize(res); return -1; } - if (sqlite3_bind_text (res, 5, rhost, -1, SQLITE_STATIC) != SQLITE_OK) + if (sqlite3_bind_text(res, 5, rhost, -1, SQLITE_STATIC) != SQLITE_OK) { if (error) - if (asprintf (error, "Failed to create add statement for 'rhost': %s", - sqlite3_errmsg (db)) < 0) + if (asprintf(error, "Failed to create add statement for 'rhost': %s", + sqlite3_errmsg(db)) < 0) *error = strdup("add_entry: Out of memory"); sqlite3_finalize(res); return -1; } - if (sqlite3_bind_text (res, 6, service, -1, SQLITE_STATIC) != SQLITE_OK) + if (sqlite3_bind_text(res, 6, service, -1, SQLITE_STATIC) != SQLITE_OK) { if (error) - if (asprintf (error, "Failed to create add statement for 'service': %s", - sqlite3_errmsg (db)) < 0) + if (asprintf(error, "Failed to create add statement for 'service': %s", + sqlite3_errmsg(db)) < 0) *error = strdup("add_entry: Out of memory"); sqlite3_finalize(res); return -1; } - int step = sqlite3_step (res); + int step = sqlite3_step(res); if (step != SQLITE_DONE) { if (error) - if (asprintf (error, "Adding an entry failed: %s", - sqlite3_errstr(step)) < 0) + if (asprintf(error, "Adding an entry failed: %s", + sqlite3_errstr(step)) < 0) *error = strdup("add_entry: Out of memory"); sqlite3_finalize(res); @@ -278,50 +279,50 @@ logout timestamp is in usec. Returns 0 on success, < 0 on failure. */ static int -update_logout (sqlite3 *db, int64_t id, uint64_t usec_logout, char **error) +update_logout(sqlite3 *db, int64_t id, uint64_t usec_logout, char **error) { sqlite3_stmt *res; char *sql = "UPDATE wtmp SET Logout = ? WHERE ID = ?"; - if (sqlite3_prepare_v2 (db, sql, -1, &res, 0) != SQLITE_OK) + if (sqlite3_prepare_v2(db, sql, -1, &res, 0) != SQLITE_OK) { if (error) - if (asprintf (error, "Failed to prepare statement (update_logout): %s", - sqlite3_errmsg (db)) < 0) - *error = strdup ("update_logout: Out of memory"); + if (asprintf(error, "Failed to prepare statement (update_logout): %s", + sqlite3_errmsg(db)) < 0) + *error = strdup("update_logout: Out of memory"); return -1; } - if (sqlite3_bind_int64 (res, 1, usec_logout) != SQLITE_OK) + if (sqlite3_bind_int64(res, 1, usec_logout) != SQLITE_OK) { if (error) - if (asprintf (error, "Failed to create update query (logout): %s", - sqlite3_errmsg (db)) < 0) + if (asprintf(error, "Failed to create update query (logout): %s", + sqlite3_errmsg(db)) < 0) *error = strdup("update_logout: Out of memory"); sqlite3_finalize(res); return -1; } - if (sqlite3_bind_int64 (res, 2, id) != SQLITE_OK) + if (sqlite3_bind_int64(res, 2, id) != SQLITE_OK) { if (error) - if (asprintf (error, "Failed to create update query (ID): %s", - sqlite3_errmsg (db)) < 0) + if (asprintf(error, "Failed to create update query (ID): %s", + sqlite3_errmsg(db)) < 0) *error = strdup("update_logout: Out of memory"); sqlite3_finalize(res); return -1; } - int step = sqlite3_step (res); + int step = sqlite3_step(res); if (step != SQLITE_DONE) { if (error) - if (asprintf (error, "Updating logout time failed: %s", - sqlite3_errstr(step)) < 0) + if (asprintf(error, "Updating logout time failed: %s", + sqlite3_errstr(step)) < 0) *error = strdup("update_logout: Out of memory"); sqlite3_finalize(res); @@ -329,18 +330,18 @@ } int changes; - if ((changes = sqlite3_changes (db)) != 1) + if ((changes = sqlite3_changes(db)) != 1) { if (error) - if (asprintf (error, "Update of logout time changed wrong number of rows, expected 1, got %d", - changes) < 0) + if (asprintf(error, "Update of logout time changed wrong number of rows, expected 1, got %d", + changes) < 0) *error = strdup("update_logout: Out of memory"); sqlite3_finalize(res); return -1; } - sqlite3_finalize (res); + sqlite3_finalize(res); return 0; } @@ -353,49 +354,49 @@ Returns 0 on success, < 0 on failure. */ int -sqlite_logout (const char *db_path, int64_t id, uint64_t usec_logout, - char **error) +sqlite_logout(const char *db_path, int64_t id, uint64_t usec_logout, + char **error) { sqlite3 *db; int r; - r = open_database_rw (db_path, &db, error); + r = open_database_rw(db_path, &db, error); if (r < 0) return r; r = update_logout(db, id, usec_logout, error); - sqlite3_close (db); + sqlite3_close(db); return r; } static int64_t -search_id (sqlite3 *db, const char *tty, char **error) +search_id(sqlite3 *db, const char *tty, char **error) { int64_t id = -1; sqlite3_stmt *res; char *sql = "SELECT ID FROM wtmp WHERE TTY = ? AND Logout IS NULL ORDER BY Login DESC LIMIT 1"; - if (sqlite3_prepare_v2 (db, sql, -1, &res, 0) != SQLITE_OK) + if (sqlite3_prepare_v2(db, sql, -1, &res, 0) != SQLITE_OK) { int r = -ENOTSUP; if (error) - if (asprintf (error, "Failed to prepare statement (search_id): %s", - sqlite3_errmsg (db)) < 0) + if (asprintf(error, "Failed to prepare statement (search_id): %s", + sqlite3_errmsg(db)) < 0) { r = -ENOMEM; - *error = strdup ("search_id: Out of memory"); + *error = strdup("search_id: Out of memory"); } return r; } - if (sqlite3_bind_text (res, 1, tty, -1, SQLITE_STATIC) != SQLITE_OK) + if (sqlite3_bind_text(res, 1, tty, -1, SQLITE_STATIC) != SQLITE_OK) { int r = -EPROTO; if (error) - if (asprintf (error, "Failed to create search query 'tty': %s", - sqlite3_errmsg (db)) < 0) + if (asprintf(error, "Failed to create search query 'tty': %s", + sqlite3_errmsg(db)) < 0) { r = -ENOMEM; *error = strdup("search_id: Out of memory"); @@ -405,15 +406,15 @@ return r; } - int step = sqlite3_step (res); + int step = sqlite3_step(res); if (step == SQLITE_ROW) - id = sqlite3_column_int64 (res, 0); + id = sqlite3_column_int64(res, 0); else if (step == SQLITE_DONE) { id = -ENOENT; if (error) - if (asprintf (error, "Open entry for tty '%s' not found (search_id)", tty) < 0) + if (asprintf(error, "Open entry for tty '%s' not found (search_id)", tty) < 0) { *error = strdup("search_id: Out of memory"); id = -ENOMEM; @@ -423,33 +424,33 @@ { id = -ENOENT; if (error) - if (asprintf (error, "Error searching open entry for tty '%s': %s", - tty, sqlite3_errstr(step)) < 0) + if (asprintf(error, "Error searching open entry for tty '%s': %s", + tty, sqlite3_errstr(step)) < 0) { *error = strdup("search_id: Out of memory"); id = -ENOMEM; } } - sqlite3_finalize (res); + sqlite3_finalize(res); return id; } int64_t -sqlite_get_id (const char *db_path, const char *tty, char **error) +sqlite_get_id(const char *db_path, const char *tty, char **error) { sqlite3 *db; int64_t retval; int r; - r = open_database_ro (db_path, &db, error); + r = open_database_ro(db_path, &db, error); if (r != 0) return -r; - retval = search_id (db, tty, error); + retval = search_id(db, tty, error); - sqlite3_close (db); + sqlite3_close(db); return retval; } @@ -458,30 +459,30 @@ each entry. Returns 0 on success, -1 on failure. */ int -sqlite_read_all (const char *db_path, - int (*cb_func)(void *unused, int argc, char **argv, - char **azColName), - void *userdata, char **error) +sqlite_read_all(const char *db_path, + int (*cb_func)(void *unused, int argc, char **argv, + char **azColName), + void *userdata, char **error) { sqlite3 *db; char *err_msg = 0; int r; - r = open_database_ro (db_path, &db, error); + r = open_database_ro(db_path, &db, error); if (r != 0) return -r; char *sql = "SELECT * FROM wtmp ORDER BY Login DESC, Logout ASC"; - r = sqlite3_exec (db, sql, cb_func, userdata, &err_msg); - sqlite3_close (db); + r = sqlite3_exec(db, sql, cb_func, userdata, &err_msg); + sqlite3_close(db); if (r != SQLITE_OK) { if (error) - if (asprintf (error, "sqlite_read_all: SQL error: %s", err_msg) < 0) - *error = strdup ("sqlite_read_all: Out of memory"); + if (asprintf(error, "sqlite_read_all: SQL error: %s", err_msg) < 0) + *error = strdup("sqlite_read_all: Out of memory"); - sqlite3_free (err_msg); + sqlite3_free(err_msg); return -r; } @@ -489,46 +490,46 @@ } static int -export_row (sqlite3 *db_dest, sqlite3_stmt *sqlStatement, char **error) +export_row(sqlite3 *db_dest, sqlite3_stmt *sqlStatement, char **error) { char *endptr; - const int type = sqlite3_column_int( sqlStatement, 1 ); - const char *user = (const char*)sqlite3_column_text( sqlStatement, 2 ); - const char *tty = (const char*)sqlite3_column_text( sqlStatement, 5 ); - const char *host = (const char*)sqlite3_column_text( sqlStatement, 6 ); - const char *service = (const char*)sqlite3_column_text( sqlStatement, 7 ); - uint64_t login_t = strtoul((const char*)sqlite3_column_text( sqlStatement, 3 ), &endptr, 10); + const int type = sqlite3_column_int(sqlStatement, 1); + const char *user = (const char*)sqlite3_column_text(sqlStatement, 2); + const char *tty = (const char*)sqlite3_column_text(sqlStatement, 5); + const char *host = (const char*)sqlite3_column_text(sqlStatement, 6); + const char *service = (const char*)sqlite3_column_text(sqlStatement, 7); + uint64_t login_t = strtoul((const char*)sqlite3_column_text(sqlStatement, 3), &endptr, 10); if ((errno == ERANGE && login_t == UINT64_MAX) - || (endptr == (const char *)sqlite3_column_text( sqlStatement, 3 )) || (*endptr != '\0')) - fprintf (stderr, "export_row: Invalid numeric time entry for 'login': '%s'\n", - sqlite3_column_text( sqlStatement, 5 )); + || (endptr == (const char *)sqlite3_column_text(sqlStatement, 3)) || (*endptr != '\0')) + fprintf(stderr, "export_row: Invalid numeric time entry for 'login': '%s'\n", + sqlite3_column_text(sqlStatement, 5)); - int64_t id = add_entry (db_dest, type, user, login_t, tty, host, - service, error); + int64_t id = add_entry(db_dest, type, user, login_t, tty, host, + service, error); if (id >=0) { - const char *logout = (const char*)sqlite3_column_text( sqlStatement, 4 ); + const char *logout = (const char*)sqlite3_column_text(sqlStatement, 4); if (logout) { uint64_t logout_t = strtoul(logout, &endptr, 10); if ((errno == ERANGE && logout_t == INT64_MAX) || (endptr == logout) || (*endptr != '\0')) - { - fprintf (stderr, "export_row: Invalid numeric time entry for 'logout': '%s'\n", sqlite3_column_text( sqlStatement, 3 )); - return -1; - } - if (update_logout (db_dest, id, logout_t, error) == -1) - { - fprintf (stderr, "export_row: Cannot update DB value: '%s'\n", *error); - return -1; - } + { + fprintf(stderr, "export_row: Invalid numeric time entry for 'logout': '%s'\n", sqlite3_column_text(sqlStatement, 3)); + return -1; + } + if (update_logout(db_dest, id, logout_t, error) == -1) + { + fprintf(stderr, "export_row: Cannot update DB value: '%s'\n", error?*error:"n/a"); + return -1; + } } } else { - fprintf (stderr, "export_row: Cannot insert DB value: '%s'\n", *error); - return -1; + fprintf(stderr, "export_row: Cannot insert DB value: '%s'\n", error?*error:"n/a"); + return -1; } return 0; @@ -545,210 +546,223 @@ sqlite3 *db_dest; uint64_t counter = 0; struct timespec threshold; - clock_gettime (CLOCK_REALTIME, &threshold); + clock_gettime(CLOCK_REALTIME, &threshold); threshold.tv_sec -= days * 86400; - struct tm *tm = localtime (&threshold.tv_sec); - uint64_t login_t = wtmpdb_timespec2usec (threshold); + struct tm *tm = localtime(&threshold.tv_sec); + uint64_t login_t = wtmpdb_timespec2usec(threshold); char date[10]; - strftime (date, 10, "%Y%m%d", tm); - char *dest_path = NULL; - char *dest_file = strdup(db_path); + strftime(date, 10, "%Y%m%d", tm); + _cleanup_free_ char *dest_path = NULL; + _cleanup_free_ char *dest_file = NULL; int r; + if ((dest_file = strdup(db_path)) == NULL) + { + if (error) + *error = strdup("sqlite_rotate: Out of memory"); + return -ENOMEM; + } + strip_extension(dest_file); - if (asprintf (&dest_path, "%s/%s_%s.db", dirname(dest_file), basename(dest_file), date) < 0) + if (asprintf(&dest_path, "%s/%s_%s.db", dirname(dest_file), basename(dest_file), date) < 0) { - *error = strdup ("sqlite_rotate: Out of memory"); + if (error) + *error = strdup("sqlite_rotate: Out of memory"); return -ENOMEM; } r = open_database_rw(dest_path, &db_dest, error); if (r < 0) + return r; + + r = open_database_rw(db_path, &db_src, error); + if (r < 0) { - free(dest_path); - free(dest_file); + sqlite3_close(db_dest); return r; } - r = open_database_rw (db_path, &db_src, error); - if (r < 0) + _cleanup_free_ char *sql_select = NULL; + if (asprintf(&sql_select, "SELECT * FROM wtmp WHERE Login <= ?" + " AND (Logout IS NOT NULL" + " OR EXISTS (SELECT 1 FROM wtmp b WHERE b.Type = %i AND b.Login > wtmp.Login))", + BOOT_TIME) < 0) { - free(dest_path); - free(dest_file); - sqlite3_close (db_dest); - return r; + if (error) + *error = strdup("sqlite_rotate: Out of memory"); + sqlite3_close(db_src); + sqlite3_close(db_dest); + return -ENOMEM; } - char *sql_select = "SELECT * FROM wtmp where Login <= ?"; sqlite3_stmt *res; - if (sqlite3_prepare_v2 (db_src, sql_select, -1, &res, 0) != SQLITE_OK) + if (sqlite3_prepare_v2(db_src, sql_select, -1, &res, 0) != SQLITE_OK) { if (error) - if (asprintf (error, "Failed to prepare statement %s (sqlite_rotate): %s", - sql_select, - sqlite3_errmsg (db_src)) < 0) - *error = strdup ("sqlite_rotate: Out of memory"); - sqlite3_close (db_src); - sqlite3_close (db_dest); - free(dest_path); - free(dest_file); + if (asprintf(error, "Failed to prepare statement %s (sqlite_rotate): %s", + sql_select, + sqlite3_errmsg(db_src)) < 0) + *error = strdup("sqlite_rotate: Out of memory"); + sqlite3_close(db_src); + sqlite3_close(db_dest); return -1; } - if (sqlite3_bind_int64 (res, 1, login_t) != SQLITE_OK) + if (sqlite3_bind_int64(res, 1, login_t) != SQLITE_OK) { if (error) - if (asprintf (error, "Failed to create rotate statement for 'login' time: %s", - sqlite3_errmsg (db_src)) < 0) + if (asprintf(error, "Failed to create rotate statement for 'login' time: %s", + sqlite3_errmsg(db_src)) < 0) *error = strdup("sqlite_rotate: Out of memory"); sqlite3_finalize(res); - sqlite3_close (db_src); - sqlite3_close (db_dest); - free(dest_path); - free(dest_file); + sqlite3_close(db_src); + sqlite3_close(db_dest); return -1; } int rc; - while ((rc = sqlite3_step(res)) == SQLITE_ROW) { - export_row (db_dest, res, error); - ++counter; - } + while ((rc = sqlite3_step(res)) == SQLITE_ROW) + { + export_row(db_dest, res, error); + ++counter; + } if (rc != SQLITE_DONE) { - if (asprintf (error, "SQL error rotating db: %s", sqlite3_errmsg(db_src)) < 0) - *error = strdup ("sqlite_rotate: Out of memory"); + if (error) + if (asprintf(error, "SQL error rotating db: %s", sqlite3_errmsg(db_src)) < 0) + *error = strdup("sqlite_rotate: Out of memory"); sqlite3_finalize(res); - sqlite3_close (db_src); - sqlite3_close (db_dest); - free(dest_path); - free(dest_file); + sqlite3_close(db_src); + sqlite3_close(db_dest); return -1; } sqlite3_finalize(res); - char *sql_delete = "DELETE FROM wtmp where Login <= ?"; - if (sqlite3_prepare_v2 (db_src, sql_delete, -1, &res, 0) != SQLITE_OK) + _cleanup_free_ char *sql_delete = NULL; + if (asprintf(&sql_delete, "DELETE FROM wtmp WHERE Login <= ?" + " AND (Logout IS NOT NULL" + " OR EXISTS (SELECT 1 FROM wtmp b WHERE b.Type = %i AND b.Login > wtmp.Login))", + BOOT_TIME) < 0) { if (error) - if (asprintf (error, "Failed to prepare statement %s (sqlite_rotate): %s", - sql_delete, - sqlite3_errmsg (db_src)) < 0) - *error = strdup ("sqlite_rotate: Out of memory"); - sqlite3_close (db_src); - sqlite3_close (db_dest); - free(dest_path); - free(dest_file); + *error = strdup("sqlite_rotate: Out of memory"); + sqlite3_close(db_src); + sqlite3_close(db_dest); + return -ENOMEM; + } + + if (sqlite3_prepare_v2(db_src, sql_delete, -1, &res, 0) != SQLITE_OK) + { + if (error) + if (asprintf(error, "Failed to prepare statement %s (sqlite_rotate): %s", + sql_delete, + sqlite3_errmsg(db_src)) < 0) + *error = strdup("sqlite_rotate: Out of memory"); + sqlite3_close(db_src); + sqlite3_close(db_dest); return -1; } - if (sqlite3_bind_int64 (res, 1, login_t) != SQLITE_OK) + if (sqlite3_bind_int64(res, 1, login_t) != SQLITE_OK) { if (error) - if (asprintf (error, "Failed to create rotate statement for 'login' time: %s", - sqlite3_errmsg (db_src)) < 0) + if (asprintf(error, "Failed to create rotate statement for 'login' time: %s", + sqlite3_errmsg(db_src)) < 0) *error = strdup("sqlite_rotate: Out of memory"); sqlite3_finalize(res); - sqlite3_close (db_src); - sqlite3_close (db_dest); - free(dest_path); - free(dest_file); + sqlite3_close(db_src); + sqlite3_close(db_dest); return -1; } - int step = sqlite3_step (res); + int step = sqlite3_step(res); if (step != SQLITE_DONE) { if (error) - if (asprintf (error, "Error rotating entry: %s", - sqlite3_errstr(step)) < 0) + if (asprintf(error, "Error rotating entry: %s", + sqlite3_errstr(step)) < 0) *error = strdup("sqlite_rotate: Out of memory"); sqlite3_finalize(res); - sqlite3_close (db_src); - sqlite3_close (db_dest); - free(dest_path); - free(dest_file); + sqlite3_close(db_src); + sqlite3_close(db_dest); return -1; } sqlite3_finalize(res); - sqlite3_close (db_src); - sqlite3_close (db_dest); + sqlite3_close(db_src); + sqlite3_close(db_dest); if (counter > 0) { if (wtmpdb_name) - *wtmpdb_name = strdup (dest_path); + *wtmpdb_name = strdup(dest_path); if (entries) *entries = counter; } else - unlink (dest_path); - - free(dest_path); - free(dest_file); + unlink(dest_path); return 0; } static uint64_t -search_boottime (sqlite3 *db, char **error) +search_boottime(sqlite3 *db, char **error) { uint64_t boottime = 0; sqlite3_stmt *res; char *sql = "SELECT Login FROM wtmp WHERE User = 'reboot' ORDER BY Login DESC LIMIT 1;"; - if (sqlite3_prepare_v2 (db, sql, -1, &res, 0) != SQLITE_OK) + if (sqlite3_prepare_v2(db, sql, -1, &res, 0) != SQLITE_OK) { if (error) - if (asprintf (error, "Failed to prepare statement (search_boottime): %s", - sqlite3_errmsg (db)) < 0) - *error = strdup ("search_boottime: Out of memory"); + if (asprintf(error, "Failed to prepare statement (search_boottime): %s", + sqlite3_errmsg(db)) < 0) + *error = strdup("search_boottime: Out of memory"); return 0; } - int step = sqlite3_step (res); + int step = sqlite3_step(res); if (step == SQLITE_ROW) - boottime = (uint64_t)sqlite3_column_int64 (res, 0); + boottime = (uint64_t)sqlite3_column_int64(res, 0); else { if (error) - if (asprintf (error, "Boot time not found: %s", - sqlite3_errstr(step)) < 0) + if (asprintf(error, "Boot time not found: %s", + sqlite3_errstr(step)) < 0) *error = strdup("search_boottime: Out of memory"); - sqlite3_finalize (res); + sqlite3_finalize(res); return 0; } - sqlite3_finalize (res); + sqlite3_finalize(res); return boottime; } int -sqlite_get_boottime (const char *db_path, - uint64_t *boottime, char **error) +sqlite_get_boottime(const char *db_path, + uint64_t *boottime, char **error) { sqlite3 *db; int r; - r = open_database_ro (db_path, &db, error); + r = open_database_ro(db_path, &db, error); if (r != 0) return -r; - *boottime = search_boottime (db, error); + *boottime = search_boottime(db, error); - sqlite3_close (db); + sqlite3_close(db); return 0; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/wtmpdb-0.75.0+git20251130.0d8fe7a/meson.build new/wtmpdb-0.76.0+git20260730.89c0861/meson.build --- old/wtmpdb-0.75.0+git20251130.0d8fe7a/meson.build 2025-11-30 17:20:54.000000000 +0100 +++ new/wtmpdb-0.76.0+git20260730.89c0861/meson.build 2026-07-30 14:48:03.000000000 +0200 @@ -12,7 +12,7 @@ 'b_lto=true', 'warning_level=2'], license : ['BSD-2-Clause'], - version : '0.75.0', + version : '0.76.0', ) conf = configuration_data() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/wtmpdb-0.75.0+git20251130.0d8fe7a/src/wtmpdb.c new/wtmpdb-0.76.0+git20260730.89c0861/src/wtmpdb.c --- old/wtmpdb-0.75.0+git20251130.0d8fe7a/src/wtmpdb.c 2025-11-30 17:20:54.000000000 +0100 +++ new/wtmpdb-0.76.0+git20260730.89c0861/src/wtmpdb.c 2026-07-30 14:48:03.000000000 +0200 @@ -314,7 +314,7 @@ if (strlen(str) >= LAST_TIMESTAMP_LEN) return str; - char *cp = strchr (str, '('); + const char *cp = strchr (str, '('); if (cp == NULL) return str; @@ -322,9 +322,9 @@ cp++; strncpy(buf, cp, LAST_TIMESTAMP_LEN); - cp = strchr (buf, ')'); - if (cp) - *cp = '\0'; + char *ptr = strchr (buf, ')'); + if (ptr) + *ptr = '\0'; return buf; } @@ -995,7 +995,6 @@ if (sd_bus_open_system (&bus) < 0) { - fprintf (stderr, "Error: cannot open dbus"); return -1; } @@ -1006,8 +1005,9 @@ &error, 'u', &soft_reboots_count); if (r < 0) { - /* systemd is too old, don't print error */ - if (!sd_bus_error_has_name (&error, SD_BUS_ERROR_UNKNOWN_PROPERTY)) + /* no systemd or systemd is too old: don't print error */ + if (!sd_bus_error_has_name (&error, SD_BUS_ERROR_SERVICE_UNKNOWN) && + !sd_bus_error_has_name (&error, SD_BUS_ERROR_UNKNOWN_PROPERTY)) { /* error occured, log it and return to fallback code */ if (error.message)
