summaryrefslogtreecommitdiffstats
path: root/liblastlog2/src/tests
diff options
context:
space:
mode:
Diffstat (limited to 'liblastlog2/src/tests')
-rw-r--r--liblastlog2/src/tests/tst_dlopen.c40
-rw-r--r--liblastlog2/src/tests/tst_pam_lastlog2_output.c115
-rw-r--r--liblastlog2/src/tests/tst_remove_entry.c88
-rw-r--r--liblastlog2/src/tests/tst_rename_user.c112
-rw-r--r--liblastlog2/src/tests/tst_write_read_user.c165
-rw-r--r--liblastlog2/src/tests/tst_y2038_ll2_read_all.c156
-rw-r--r--liblastlog2/src/tests/tst_y2038_sqlite3_time.c83
7 files changed, 759 insertions, 0 deletions
diff --git a/liblastlog2/src/tests/tst_dlopen.c b/liblastlog2/src/tests/tst_dlopen.c
new file mode 100644
index 0000000..112564b
--- /dev/null
+++ b/liblastlog2/src/tests/tst_dlopen.c
@@ -0,0 +1,40 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later
+
+ Copyright (C) Nalin Dahyabhai <nalin@redhat.com> 2003
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+*/
+
+#include <dlfcn.h>
+#include <stdio.h>
+#include <limits.h>
+#include <sys/stat.h>
+
+/* Simple program to see if dlopen() would succeed. */
+int main(int argc, char **argv)
+{
+ int i;
+ struct stat st;
+ char buf[PATH_MAX];
+
+ for (i = 1; i < argc; i++) {
+ if (dlopen(argv[i], RTLD_NOW)) {
+ fprintf(stdout, "dlopen() of \"%s\" succeeded.\n",
+ argv[i]);
+ } else {
+ snprintf(buf, sizeof(buf), "./%s", argv[i]);
+ if ((stat(buf, &st) == 0) && dlopen(buf, RTLD_NOW)) {
+ fprintf(stdout, "dlopen() of \"./%s\" "
+ "succeeded.\n", argv[i]);
+ } else {
+ fprintf(stdout, "dlopen() of \"%s\" failed: "
+ "%s\n", argv[i], dlerror());
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
diff --git a/liblastlog2/src/tests/tst_pam_lastlog2_output.c b/liblastlog2/src/tests/tst_pam_lastlog2_output.c
new file mode 100644
index 0000000..1fd1eec
--- /dev/null
+++ b/liblastlog2/src/tests/tst_pam_lastlog2_output.c
@@ -0,0 +1,115 @@
+/* SPDX-License-Identifier: BSD-2-Clause
+
+ Copyright (c) 2023, Thorsten Kukuk <kukuk@suse.com>
+
+ 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.
+*/
+
+/* Test case:
+ Store defined data into the database, read it, create the time
+ string like pam_lastlog2 does, compare the result.
+*/
+
+#include <time.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+
+#include "lastlog2P.h"
+
+const char *expected = "Last login: Mon Mar 13 07:13:41 UTC 2023 from 192.168.122.1 on pts/0";
+const time_t login_time = 1678691621;
+int
+main(void)
+{
+ const char *user = "root";
+ struct ll2_context *context = ll2_new_context("pam_lastlog2-output.db");
+ int64_t ll_time = 0;
+ char *tty = NULL;
+ char *rhost = NULL;
+ char *date = NULL;
+ char the_time[256];
+ char *error = NULL;
+ char *output = NULL;
+
+ if (ll2_write_entry (context, user, login_time, "pts/0",
+ "192.168.122.1", NULL, &error) != 0) {
+ if (error) {
+ fprintf (stderr, "%s\n", error);
+ free (error);
+ } else
+ fprintf (stderr, "ll2_write_entry failed\n");
+ ll2_unref_context(context);
+ return 1;
+ }
+
+ if (ll2_read_entry (context, user, &ll_time, &tty, &rhost,
+ NULL, &error) != 0) {
+ if (error) {
+ fprintf (stderr, "%s\n", error);
+ free (error);
+ } else
+ fprintf (stderr, "Unknown error reading database %s", context ? context->lastlog2_path : "NULL");
+ ll2_unref_context(context);
+ return 1;
+ }
+
+ if (ll_time) {
+ struct tm *tm, tm_buf;
+ /* this is necessary if you compile this on architectures with
+ a 32bit time_t type. */
+ time_t t_time = ll_time;
+
+ if ((tm = localtime_r (&t_time, &tm_buf)) != NULL) {
+ strftime (the_time, sizeof (the_time),
+ " %a %b %e %H:%M:%S %Z %Y", tm);
+ date = the_time;
+ }
+ }
+
+ if (asprintf (&output, "Last login:%s%s%s%s%s",
+ date ? date : "",
+ rhost ? " from " : "",
+ rhost ? rhost : "",
+ tty ? " on " : "",
+ tty ? tty : "") < 0) {
+ fprintf (stderr, "Out of memory!\n");
+ ll2_unref_context(context);
+ return 1;
+ }
+
+ if (strcmp (output, expected) != 0) {
+ fprintf (stderr, "Output '%s'\n does not match '%s'\n",
+ output, expected);
+ ll2_unref_context(context);
+ return 1;
+ }
+
+ ll2_unref_context(context);
+ free (output);
+ free (tty);
+ free (rhost);
+
+ return 0;
+}
diff --git a/liblastlog2/src/tests/tst_remove_entry.c b/liblastlog2/src/tests/tst_remove_entry.c
new file mode 100644
index 0000000..39079c8
--- /dev/null
+++ b/liblastlog2/src/tests/tst_remove_entry.c
@@ -0,0 +1,88 @@
+/* SPDX-License-Identifier: BSD-2-Clause
+
+ Copyright (c) 2023, Thorsten Kukuk <kukuk@suse.com>
+
+ 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.
+*/
+
+/* Test case:
+ Create an entry, delete that entry, and try to read entry again.
+ Reading the entry should fail.
+*/
+
+#include <time.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "lastlog2.h"
+
+int
+main(void)
+{
+ const char *user = "user";
+ struct ll2_context *context = ll2_new_context("tst-delete-user.db");
+ int64_t ll_time = 0;
+ char *tty = NULL;
+ char *rhost = NULL;
+ char *service = NULL;
+ char *error = NULL;
+
+ if (ll2_write_entry (context, user, time (NULL), "test-tty",
+ "localhost", "sshd", &error) != 0) {
+ if (error) {
+ fprintf (stderr, "%s\n", error);
+ free (error);
+ } else
+ fprintf (stderr, "ll2_write_entry failed\n");
+ ll2_unref_context(context);
+ return 1;
+ }
+
+ if (ll2_remove_entry (context, user, &error) != 0) {
+ if (error) {
+ fprintf (stderr, "%s\n", error);
+ free (error);
+ } else
+ fprintf (stderr, "ll2_remove_entry failed\n");
+ ll2_unref_context(context);
+ return 1;
+ }
+
+ /* this needs to fail, as the old entry shouldn't exist anymore. */
+ if (ll2_read_entry (context, user, &ll_time, &tty, &rhost, &service, &error) == 0) {
+ fprintf (stderr, "Reading old user from database did not fail!\n");
+ fprintf (stderr, "ll_time=%lld, tty='%s', rhost='%s', service='%s'\n",
+ (long long int)ll_time, tty, rhost, service);
+ ll2_unref_context(context);
+ return 1;
+ }
+
+ ll2_unref_context(context);
+ free (error);
+ free (tty);
+ free (rhost);
+ free (service);
+
+ return 0;
+}
diff --git a/liblastlog2/src/tests/tst_rename_user.c b/liblastlog2/src/tests/tst_rename_user.c
new file mode 100644
index 0000000..a1788b5
--- /dev/null
+++ b/liblastlog2/src/tests/tst_rename_user.c
@@ -0,0 +1,112 @@
+/* SPDX-License-Identifier: BSD-2-Clause
+
+ Copyright (c) 2023, Thorsten Kukuk <kukuk@suse.com>
+
+ 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.
+*/
+
+/* Test case:
+ Create an entry, rename that entry, and try to read the old and
+ new entry again. Reading the old entry should fail.
+*/
+
+#include <time.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "lastlog2P.h"
+
+int
+main(void)
+{
+ const char *user = "user";
+ const char *newname = "new";
+ struct ll2_context *context = ll2_new_context("tst-rename-user.db");
+ int64_t ll_time = 0;
+ char *tty = NULL;
+ char *rhost = NULL;
+ char *service = NULL;
+ char *error = NULL;
+
+ if (ll2_write_entry (context, user, time (NULL), "test-tty",
+ "localhost", "test-service", &error) != 0) {
+ if (error) {
+ fprintf (stderr, "%s\n", error);
+ free (error);
+ }
+ else
+ fprintf (stderr, "ll2_write_entry failed\n");
+ ll2_unref_context(context);
+ return 1;
+ }
+
+ if (ll2_rename_user (context, user, newname, &error) != 0) {
+ if (error) {
+ fprintf (stderr, "%s\n", error);
+ free (error);
+ }
+ else
+ fprintf (stderr, "ll2_rename_user failed\n");
+ ll2_unref_context(context);
+ return 1;
+ }
+
+ /* this needs to fail, as the old entry shouldn't exist anymore. */
+ if (ll2_read_entry (context, user, &ll_time, &tty, &rhost,
+ &service, &error) == 0) {
+ fprintf (stderr, "Reading old user from database did not fail!\n");
+ fprintf (stderr, "ll_time=%lld, tty='%s', rhost='%s', service='%s'\n",
+ (long long int)ll_time, tty, rhost, service);
+ ll2_unref_context(context);
+ return 1;
+ }
+
+ if (error) {
+ free (error);
+ error = NULL;
+ }
+
+ if (ll2_read_entry (context, newname, &ll_time, &tty, &rhost, &service,
+ &error) != 0) {
+ if (error) {
+ fprintf (stderr, "%s\n", error);
+ free (error);
+ } else
+ fprintf (stderr, "Unknown error reading database %s", context->lastlog2_path);
+ ll2_unref_context(context);
+ return 1;
+ }
+
+ if (strcmp (tty, "test-tty") != 0 || strcmp (rhost, "localhost") != 0 ||
+ strcmp (service, "test-service") != 0) {
+ fprintf (stderr, "New entry data does not match old entry data!\n");
+ }
+
+ ll2_unref_context(context);
+ free (tty);
+ free (rhost);
+ free (service);
+
+ return 0;
+}
diff --git a/liblastlog2/src/tests/tst_write_read_user.c b/liblastlog2/src/tests/tst_write_read_user.c
new file mode 100644
index 0000000..dbf1db7
--- /dev/null
+++ b/liblastlog2/src/tests/tst_write_read_user.c
@@ -0,0 +1,165 @@
+/* SPDX-License-Identifier: BSD-2-Clause
+
+ Copyright (c) 2023, Thorsten Kukuk <kukuk@suse.com>
+
+ 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.
+*/
+
+/* Test case:
+ Create an entry, rename that entry, and try to read the old and
+ new entry again. Reading the old entry should fail.
+*/
+
+#include <time.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include "lastlog2P.h"
+
+static int
+test_args (struct ll2_context *context, const char *user, int64_t ll_time,
+ const char *tty, const char *rhost, const char *service)
+{
+ char *error = NULL;
+ int64_t res_time;
+ char *res_tty = NULL;
+ char *res_rhost = NULL;
+ char *res_service = NULL;
+
+ if (ll2_write_entry (context, user, ll_time, tty, rhost, service, &error) != 0) {
+ if (error) {
+ fprintf (stderr, "%s\n", error);
+ free (error);
+ } else
+ fprintf (stderr, "ll2_write_entry failed\n");
+ return 1;
+ }
+
+ if (ll2_read_entry (context, user, &res_time, &res_tty, &res_rhost, &res_service, &error) != 0) {
+ if (error) {
+ fprintf (stderr, "%s\n", error);
+ free (error);
+ } else
+ fprintf (stderr, "Unknown error reading database %s", context->lastlog2_path);
+ return 1;
+ }
+
+ if (ll_time != res_time) {
+ fprintf (stderr, "Wrong time: got %lld, expect %lld\n",
+ (long long int)res_time, (long long int)ll_time);
+ return 1;
+ }
+
+ if ((tty == NULL && res_tty != NULL) ||
+ (tty != NULL && res_tty == NULL) ||
+ (tty != NULL && res_tty != NULL && strcmp (tty, res_tty) != 0)) {
+ fprintf (stderr, "Wrong tty: got %s, expect %s\n", tty, res_tty);
+ return 1;
+ }
+
+ if ((rhost == NULL && res_rhost != NULL) ||
+ (rhost != NULL && res_rhost == NULL) ||
+ (rhost != NULL && res_rhost != NULL && strcmp (rhost, res_rhost) != 0)) {
+ fprintf (stderr, "Wrong rhost: got %s, expect %s\n", rhost, res_rhost);
+ return 1;
+ }
+
+ if ((service == NULL && res_service != NULL) ||
+ (service != NULL && res_service == NULL) ||
+ (service != NULL && res_service != NULL && strcmp (service, res_service) != 0)) {
+ fprintf (stderr, "Wrong service: got %s, expect %s\n", service, res_service);
+ return 1;
+ }
+
+
+ free (res_tty);
+ free (res_rhost);
+ free (res_service);
+
+ return 0;
+}
+
+int
+main(void)
+{
+ struct ll2_context *context = ll2_new_context("tst-write-read-user.db");
+ char *error = NULL;
+ int64_t res_time;
+ char *res_tty = NULL;
+ char *res_rhost = NULL;
+ char *res_service = NULL;
+
+ if (test_args (context, "user1", time (NULL), "test-tty", "localhost", "test") != 0) {
+ ll2_unref_context(context);
+ return 1;
+ }
+ if (test_args (context, "user2", 0, NULL, NULL, NULL) != 0) {
+ ll2_unref_context(context);
+ return 1;
+ }
+ if (test_args (context, "user3", time (NULL), NULL, NULL, NULL) != 0) {
+ ll2_unref_context(context);
+ return 1;
+ }
+ if (test_args (context, "user4", time (NULL), "test-tty", NULL, NULL) != 0) {
+ ll2_unref_context(context);
+ return 1;
+ }
+ if (test_args (context, "user5", time (NULL), NULL, "localhost", NULL) != 0) {
+ ll2_unref_context(context);
+ return 1;
+ }
+
+ /* Checking errno if the db file does not exist */
+ struct ll2_context *context_not_found = ll2_new_context("no_file");
+ if (ll2_read_entry (context_not_found, "user", &res_time, &res_tty, &res_rhost, &res_service, &error) != 0) {
+ if (error) {
+ fprintf (stderr, "%s\n", error);
+ free (error);
+ } else
+ fprintf (stderr, "Couldn't read entries for all users\n");
+
+ if(errno) {
+ if (errno == ENOENT)
+ {
+ fprintf (stderr, "Returning the correct errno: %s\n",
+ strerror (errno));
+ ll2_unref_context(context_not_found);
+ return 0;
+ }
+ fprintf (stderr, "errno: %s\n",
+ strerror (errno));
+ } else {
+ fprintf (stderr, "errno: NULL\n");
+ }
+
+ ll2_unref_context(context_not_found);
+ ll2_unref_context(context);
+ return 1;
+ }
+
+ ll2_unref_context(context);
+ return 0;
+}
diff --git a/liblastlog2/src/tests/tst_y2038_ll2_read_all.c b/liblastlog2/src/tests/tst_y2038_ll2_read_all.c
new file mode 100644
index 0000000..014ae9d
--- /dev/null
+++ b/liblastlog2/src/tests/tst_y2038_ll2_read_all.c
@@ -0,0 +1,156 @@
+/* SPDX-License-Identifier: BSD-2-Clause
+
+ Copyright (c) 2023, Thorsten Kukuk <kukuk@suse.com>
+
+ 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.
+*/
+
+/* Test case:
+ Create an entry with an 3*INT32_MAX timestamp, store that,
+ read that via ll2_read_all callback again and make sure the
+ timestamp is correct.
+*/
+
+#include <time.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <errno.h>
+
+#include "lastlog2P.h"
+
+#define BIG_TIME_VALUE ((int64_t)3*INT32_MAX)
+
+const char *user = "y2038";
+const char *on_tty = "pts/test";
+const char *rhost = NULL;
+const char *service = "sshd";
+
+static int
+check_y2038 (const char *res_user, int64_t ll_time, const char *res_tty,
+ const char *res_rhost, const char *res_service, const char *error)
+{
+
+ if (strcmp (user, res_user) != 0) {
+ fprintf (stderr, "write/read entry user mismatch: written: %s, got: %s\n",
+ user, res_user);
+ exit (1);
+ }
+
+ if (ll_time != BIG_TIME_VALUE) {
+ fprintf (stderr, "write/read entry time mismatch: written: %lld, got: %lld\n",
+ (long long int)BIG_TIME_VALUE, (long long int)ll_time);
+ exit (1);
+ }
+
+ if (strcmp (on_tty, res_tty) != 0) {
+ fprintf (stderr, "write/read entry tty mismatch: written: %s, got: %s\n",
+ on_tty, res_tty);
+ exit (1);
+ }
+
+ if (rhost != NULL) {
+ fprintf (stderr, "write/read entry rhost mismatch: written: NULL, got: %s\n",
+ res_rhost);
+ exit (1);
+ }
+
+ if (strcmp (service, res_service) != 0) {
+ fprintf (stderr, "write/read entry service mismatch: written: %s, got: %s\n",
+ service, res_service);
+ exit (1);
+ }
+
+ if (error != NULL) {
+ fprintf (stderr, "got error: %s\n",
+ error);
+ exit (1);
+ }
+
+ return 0;
+}
+
+int
+main(void)
+{
+ struct ll2_context *context = ll2_new_context("y2038-ll2_read_all.db");
+ char *error = NULL;
+
+ remove (context->lastlog2_path);
+
+ printf ("Big time value is: %lld\n", (long long int)BIG_TIME_VALUE);
+
+ if (ll2_write_entry (context, user, BIG_TIME_VALUE, on_tty, rhost, service,
+ &error) != 0) {
+ if (error) {
+ fprintf (stderr, "%s\n", error);
+ free (error);
+ }
+ else
+ fprintf (stderr, "ll2_write_entry failed\n");
+ ll2_unref_context(context);
+ return 1;
+ }
+
+ if (ll2_read_all (context, check_y2038, &error) != 0) {
+ if (error) {
+ fprintf (stderr, "%s\n", error);
+ free (error);
+ } else
+ fprintf (stderr, "Couldn't read entries for all users\n");
+ ll2_unref_context(context);
+ return 1;
+ }
+
+ /* Checking errno if the db file does not exist */
+ remove (context->lastlog2_path);
+
+ if (ll2_read_all (context, check_y2038, &error) != 0) {
+ if (error) {
+ fprintf (stderr, "%s\n", error);
+ free (error);
+ } else
+ fprintf (stderr, "Couldn't read entries for all users\n");
+
+ if(errno) {
+ if (errno == ENOENT)
+ {
+ fprintf (stderr, "Returning the correct errno: %s\n",
+ strerror (errno));
+ ll2_unref_context(context);
+ return 0;
+ }
+ fprintf (stderr, "errno: %s\n",
+ strerror (errno));
+ } else {
+ fprintf (stderr, "errno: NULL\n");
+ }
+
+ ll2_unref_context(context);
+ return 1;
+ }
+
+ ll2_unref_context(context);
+ return 0;
+}
diff --git a/liblastlog2/src/tests/tst_y2038_sqlite3_time.c b/liblastlog2/src/tests/tst_y2038_sqlite3_time.c
new file mode 100644
index 0000000..a296634
--- /dev/null
+++ b/liblastlog2/src/tests/tst_y2038_sqlite3_time.c
@@ -0,0 +1,83 @@
+/* SPDX-License-Identifier: BSD-2-Clause
+
+ Copyright (c) 2023, Thorsten Kukuk <kukuk@suse.com>
+
+ 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.
+*/
+
+/* Test case:
+ Create an entry with an INT64_MAX-1000 timestamp, store that,
+ read that again and make sure the timestamp is correct.
+*/
+
+#include <time.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+
+#include "lastlog2P.h"
+
+#define BIG_TIME_VALUE (INT64_MAX - 1000)
+
+int
+main(void)
+{
+ const char *user = "y2038";
+ struct ll2_context *context = ll2_new_context("y2038-sqlite3-time.db");
+ int64_t ll_time = 0;
+ char *error = NULL;
+
+ printf ("Big time value is: %lld\n", (long long int)BIG_TIME_VALUE);
+
+ if (ll2_write_entry (context, user, BIG_TIME_VALUE, NULL, NULL,
+ NULL, &error) != 0) {
+ if (error) {
+ fprintf (stderr, "%s\n", error);
+ free (error);
+ } else
+ fprintf (stderr, "ll2_write_entry failed\n");
+ ll2_unref_context(context);
+ return 1;
+ }
+
+ if (ll2_read_entry (context, user, &ll_time, NULL, NULL, NULL,
+ &error) != 0) {
+ if (error) {
+ fprintf (stderr, "%s\n", error);
+ free (error);
+ } else
+ fprintf (stderr, "Unknown error reading database %s", context->lastlog2_path);
+ ll2_unref_context(context);
+ return 1;
+ }
+
+ if (ll_time != BIG_TIME_VALUE) {
+ fprintf (stderr, "write/read entry time mismatch: written: %lld, got: %lld\n",
+ (long long int)BIG_TIME_VALUE, (long long int)ll_time);
+ ll2_unref_context(context);
+ return 1;
+ }
+
+ ll2_unref_context(context);
+ return 0;
+}