--- /dev/null
+//po4a: entry man manual
+= ll2_get_journal_mode(3)
+:doctype: manpage
+:man manual: Programmer's Manual
+:man source: util-linux {release-version}
+:page-layout: base
+:lib: liblastlog2
+:firstversion: 2.43
+
+== NAME
+
+ll2_get_journal_mode - get current SQLite journal mode for lastlog2 database
+
+== SYNOPSIS
+
+*#include <lastlog2.h>*
+
+*int ll2_get_journal_mode(struct ll2_context *__context__, char **__mode__, char **__error__);*
+
+== DESCRIPTION
+
+The *ll2_get_journal_mode*() function retrieves the current SQLite journal mode
+for the lastlog2 database associated with _context_.
+
+If _context_ is NULL, the default database, defined in _LL2_DEFAULT_DATABASE_,
+will be taken.
+
+The returned journal mode string is in uppercase (e.g., "WAL", "DELETE") for
+consistency with user input.
+
+Common journal modes include:
+
+* *WAL* - Write-Ahead Logging mode
+* *DELETE* - Default mode
+* *TRUNCATE* - Truncate mode
+* *PERSIST* - Persist mode
+* *MEMORY* - Memory mode
+* *OFF* - Journaling disabled
+
+--------------------------------------
+struct ll2_context *ctx;
+char *mode = NULL;
+char *error = NULL;
+
+ctx = ll2_new_context(NULL);
+if (!ctx) {
+ fprintf(stderr, "Failed to create context\n");
+ return 1;
+}
+
+if (ll2_get_journal_mode(ctx, &mode, &error) != 0) {
+ fprintf(stderr, "Failed to get journal mode: %s\n", error);
+ free(error);
+ ll2_unref_context(ctx);
+ return 1;
+}
+
+printf("Current journal mode: %s\n", mode);
+free(mode);
+ll2_unref_context(ctx);
+--------------------------------------
+
+== RETURN VALUE
+
+Returns 0 on success, -ENOMEM or -1 on other failure.
+_error_ contains an error string if the return value is -1.
+_error_ is not guaranteed to contain an error string, could also be NULL.
+_error_ should be freed by the caller.
+If successful, _mode_ will be set to a newly allocated string containing
+the current journal mode. The caller must free this string.
+
+== AUTHORS
+
+mailto:kukuk@suse.de[Thorsten Kukuk],
+mailto:wanbingjiang@webray.com.cn[WanBingjiang]
+
+== SEE ALSO
+
+*lastlog2*(3),
+*ll2_set_journal_mode*(3),
+*ll2_new_context*(3),
+*ll2_unref_context*(3),
+*ll2_read_all*(3),
+*ll2_write_entry*(3),
+*ll2_read_entry*(3),
+*ll2_remove_entry*(3),
+*ll2_update_login_time*(3),
+*ll2_import_lastlog*(3)
+
+include::man-common/bugreports.adoc[]
+
+include::man-common/footer-lib.adoc[]
+
+ifdef::translation[]
+include::man-common/translation.adoc[]
+endif::[]
--- /dev/null
+//po4a: entry man manual
+= ll2_set_journal_mode(3)
+:doctype: manpage
+:man manual: Programmer's Manual
+:man source: util-linux {release-version}
+:page-layout: base
+:lib: liblastlog2
+:firstversion: 2.43
+
+== NAME
+
+ll2_set_journal_mode - set SQLite journal mode for lastlog2 database
+
+== SYNOPSIS
+
+*#include <lastlog2.h>*
+
+*int ll2_set_journal_mode(struct ll2_context *__context__, const char *__mode__, char **__error__);*
+
+== DESCRIPTION
+
+The *ll2_set_journal_mode*() function sets the SQLite journal mode for the
+lastlog2 database associated with _context_ to the specified _mode_.
+
+If _context_ is NULL, the default database, defined in _LL2_DEFAULT_DATABASE_,
+will be taken.
+
+The journal mode setting is persistent and will be retained across database
+connections.
+
+Common journal modes include:
+
+* *WAL* - Write-Ahead Logging mode (recommended for high concurrency)
+* *DELETE* - Default mode, deletes journal file after commit
+* *TRUNCATE* - Truncates journal file to zero length after commit
+* *PERSIST* - Keeps journal file after commit
+* *MEMORY* - Stores journal in memory
+* *OFF* - Disables journaling (not recommended)
+
+WAL (Write-Ahead Logging) mode is recommended for high-concurrency scenarios
+as it allows readers and writers to operate concurrently without blocking
+each other. This significantly reduces database lock contention in environments
+with frequent SSH logins.
+
+--------------------------------------
+struct ll2_context *ctx;
+char *error = NULL;
+
+ctx = ll2_new_context(NULL);
+if (!ctx) {
+ fprintf(stderr, "Failed to create context\n");
+ return 1;
+}
+
+if (ll2_set_journal_mode(ctx, "WAL", &error) != 0) {
+ fprintf(stderr, "Failed to set journal mode: %s\n", error);
+ free(error);
+ ll2_unref_context(ctx);
+ return 1;
+}
+
+ll2_unref_context(ctx);
+--------------------------------------
+
+== RETURN VALUE
+
+Returns 0 on success, -ENOMEM or -1 on other failure.
+_error_ contains an error string if the return value is -1.
+_error_ is not guaranteed to contain an error string, could also be NULL.
+_error_ should be freed by the caller.
+
+== AUTHORS
+
+mailto:kukuk@suse.de[Thorsten Kukuk],
+mailto:wanbingjiang@webray.com.cn[WanBingjiang]
+
+== SEE ALSO
+
+*lastlog2*(3),
+*ll2_get_journal_mode*(3),
+*ll2_new_context*(3),
+*ll2_unref_context*(3),
+*ll2_read_all*(3),
+*ll2_write_entry*(3),
+*ll2_read_entry*(3),
+*ll2_remove_entry*(3),
+*ll2_update_login_time*(3),
+*ll2_import_lastlog*(3)
+
+include::man-common/bugreports.adoc[]
+
+include::man-common/footer-lib.adoc[]
+
+ifdef::translation[]
+include::man-common/translation.adoc[]
+endif::[]
*/
#include <pwd.h>
+#include <ctype.h>
#include <errno.h>
#include <time.h>
#include <stdio.h>
return retval;
}
+
+static const char *valid_journal_modes[] = {
+ "WAL", "DELETE", "TRUNCATE", "PERSIST", "MEMORY", "OFF", NULL
+};
+
+static int
+is_valid_journal_mode(const char *mode)
+{
+ for (size_t i = 0; valid_journal_modes[i]; i++)
+ if (strcasecmp(mode, valid_journal_modes[i]) == 0)
+ return 1;
+ return 0;
+}
+
+/* Set journal mode.
+ Returns 0 on success, -ENOMEM or -1 on other failure. */
+extern int
+ll2_set_journal_mode(struct ll2_context *context, const char *mode,
+ char **error)
+{
+ sqlite3 *db;
+ sqlite3_stmt *res = NULL;
+ const unsigned char *actual;
+ char *sql = NULL;
+ int retval = 0;
+
+ if (!mode || !is_valid_journal_mode(mode)) {
+ if (error && asprintf(error, "Invalid journal mode: %s", mode ? mode : "(null)") < 0)
+ return -ENOMEM;
+ return -1;
+ }
+
+ retval = open_database_rw(context, &db, error);
+ if (retval != 0)
+ return retval;
+
+ if (asprintf(&sql, "PRAGMA journal_mode = %s;", mode) < 0) {
+ sqlite3_close(db);
+ return -ENOMEM;
+ }
+
+ if (sqlite3_prepare_v2(db, sql, -1, &res, 0) != SQLITE_OK) {
+ retval = -1;
+ if (error && asprintf(error, "Failed to set journal mode to %s: %s",
+ mode, sqlite3_errmsg(db)) < 0)
+ retval = -ENOMEM;
+ goto out;
+ }
+
+ if (sqlite3_step(res) != SQLITE_ROW) {
+ retval = -1;
+ if (error && asprintf(error, "Failed to set journal mode to %s: %s",
+ mode, sqlite3_errmsg(db)) < 0)
+ retval = -ENOMEM;
+ goto out;
+ }
+
+ /* Verify SQLite actually applied the requested mode */
+ actual = sqlite3_column_text(res, 0);
+ if (!actual || strcasecmp((const char *)actual, mode) != 0) {
+ retval = -1;
+ if (error && asprintf(error,
+ "Journal mode not changed: requested %s, got %s",
+ mode, actual ? (const char *)actual : "(null)") < 0)
+ retval = -ENOMEM;
+ }
+
+out:
+ if (res)
+ sqlite3_finalize(res);
+ free(sql);
+ sqlite3_close(db);
+
+ return retval;
+}
+
+/* Get current journal mode.
+ Returns 0 on success, -ENOMEM or -1 on other failure. */
+extern int
+ll2_get_journal_mode(struct ll2_context *context, char **mode, char **error)
+{
+ sqlite3 *db;
+ sqlite3_stmt *res = NULL;
+ int retval = 0;
+ static const char *sql = "PRAGMA journal_mode;";
+
+ retval = open_database_ro(context, &db, error);
+ if (retval != 0)
+ return retval;
+
+ if (sqlite3_prepare_v2(db, sql, -1, &res, 0) != SQLITE_OK) {
+ retval = -1;
+ if (error && asprintf(error, "Failed to query journal mode: %s",
+ sqlite3_errmsg(db)) < 0)
+ retval = -ENOMEM;
+ goto out;
+ }
+
+ int step = sqlite3_step(res);
+ if (step == SQLITE_ROW) {
+ const unsigned char *mode_str = sqlite3_column_text(res, 0);
+ if (mode_str && mode) {
+ *mode = strdup((const char *)mode_str);
+ if (*mode == NULL) {
+ retval = -ENOMEM;
+ } else {
+ /* Convert to uppercase for consistency */
+ for (char *p = *mode; *p; p++)
+ *p = toupper((unsigned char)*p);
+ }
+ }
+ } else {
+ retval = -1;
+ if (error && asprintf(error, "Failed to get journal mode: %s",
+ sqlite3_errmsg(db)) < 0)
+ retval = -ENOMEM;
+ }
+
+out:
+ if (res)
+ sqlite3_finalize(res);
+ sqlite3_close(db);
+
+ return retval;
+}
extern int ll2_import_lastlog (struct ll2_context *context,
const char *lastlog_file, char **error);
+/* Set journal mode (e.g., "WAL", "DELETE").
+ Returns 0 on success, -ENOMEM or -1 on other failure. */
+extern int ll2_set_journal_mode (struct ll2_context *context,
+ const char *mode, char **error);
+
+/* Get current journal mode.
+ Returns 0 on success, -ENOMEM or -1 on other failure.
+ Caller must free the returned mode string. */
+extern int ll2_get_journal_mode (struct ll2_context *context,
+ char **mode, char **error);
+
#ifdef __cplusplus
}
#endif
ll2_import_lastlog;
local: *;
};
+
+LIBLASTLOG2_2_43 {
+ global:
+ ll2_set_journal_mode;
+ ll2_get_journal_mode;
+} LIBLASTLOG2_2_40;