Log to /var/log/apk.log

This adds a log file at /var/log/apk.log. On each run, apk's version
information and the current date & time are written to this file,
followed by any normal apk output.
cute-signatures
Drew DeVault 2021-02-14 10:01:02 -05:00 committed by Timo Teräs
parent 4fe5ac8328
commit 646c834492
5 changed files with 61 additions and 10 deletions

View File

@ -15,6 +15,8 @@ to install is called the _world_ (see *apk-world*(5)). *apk* supports various
sub-commands to query and manipulate _world_ and local & remote package
repositories.
All apk commands which modify the database are logged to /var/log/apk.log.
# COMMANDS
Each command is documented in detail on its manual page.

View File

@ -46,11 +46,11 @@ time_t time(time_t *tloc)
}
#endif
static void version(struct apk_out *out)
static void version(struct apk_out *out, const char *prefix)
{
apk_out(out, "apk-tools " APK_VERSION ", compiled for " APK_DEFAULT_ARCH ".");
apk_out_fmt(out, prefix, "apk-tools " APK_VERSION ", compiled for " APK_DEFAULT_ARCH ".");
#ifdef TEST_MODE
apk_out(out, "TEST MODE BUILD. NOT FOR PRODUCTION USE.");
apk_out_fmt(out, prefix, "TEST MODE BUILD. NOT FOR PRODUCTION USE.");
#endif
}
@ -122,7 +122,7 @@ static int option_parse_global(void *ctx, struct apk_ctx *ac, int opt, const cha
ac->out.verbosity++;
break;
case OPT_GLOBAL_version:
version(out);
version(out, NULL);
return -ESHUTDOWN;
case OPT_GLOBAL_force:
ac->force |= APK_FORCE_OVERWRITE | APK_FORCE_OLD_APK
@ -260,7 +260,7 @@ const struct apk_option_group optgroup_commit = {
static int usage(struct apk_out *out, struct apk_applet *applet)
{
version(out);
version(out, NULL);
apk_applet_help(applet, out);
return 1;
}
@ -460,6 +460,9 @@ int main(int argc, char **argv)
r = apk_ctx_prepare(&ctx);
if (r != 0) goto err;
apk_out_log_argv(&ctx.out, apk_argv);
version(&ctx.out, APK_OUT_LOG_ONLY);
if (ctx.open_flags) {
r = apk_db_open(&db, &ctx);
if (r != 0) {

View File

@ -30,11 +30,15 @@ void apk_url_parse(struct apk_url_print *, const char *);
struct apk_out {
int verbosity;
unsigned int width, last_change;
FILE *out, *err;
FILE *out, *err, *log;
};
static inline int apk_out_verbosity(struct apk_out *out) { return out->verbosity; }
// Pass this as the prefix to skip logging to the console (but still write to
// the log file).
#define APK_OUT_LOG_ONLY ((const char*)-1)
#define apk_err(out, args...) do { apk_out_fmt(out, "ERROR: ", args); } while (0)
#define apk_out(out, args...) do { apk_out_fmt(out, NULL, args); } while (0)
#define apk_warn(out, args...) do { if (apk_out_verbosity(out) >= 0) { apk_out_fmt(out, "WARNING: ", args); } } while (0)
@ -44,6 +48,7 @@ static inline int apk_out_verbosity(struct apk_out *out) { return out->verbosity
void apk_out_reset(struct apk_out *);
void apk_out_fmt(struct apk_out *, const char *prefix, const char *format, ...);
void apk_out_log_argv(struct apk_out *, char **argv);
struct apk_progress {
struct apk_out *out;

View File

@ -29,6 +29,7 @@ void apk_ctx_free(struct apk_ctx *ac)
apk_trust_free(&ac->trust);
apk_string_array_free(&ac->repository_list);
apk_string_array_free(&ac->private_keys);
if (ac->out.log) fclose(ac->out.log);
}
int apk_ctx_prepare(struct apk_ctx *ac)
@ -53,6 +54,21 @@ int apk_ctx_prepare(struct apk_ctx *ac)
apk_err(&ac->out, "Unable to open root: %s", apk_error_str(errno));
return -errno;
}
if (ac->open_flags & APK_OPENF_WRITE) {
const char *log_path = "var/log/apk.log", *log_dir = "var/log";
const int lflags = O_WRONLY | O_APPEND | O_CREAT | O_CLOEXEC;
int fd = openat(ac->root_fd, log_path, lflags, 0644);
if (fd < 0 && (ac->open_flags & APK_OPENF_CREATE)) {
mkdirat(ac->root_fd, log_dir, 0755);
fd = openat(ac->root_fd, log_path, lflags, 0644);
}
if (fd < 0) {
apk_err(&ac->out, "Unable to open log: %s", apk_error_str(errno));
return -errno;
}
ac->out.log = fdopen(fd, "a");
}
return 0;
}

View File

@ -136,10 +136,35 @@ static void log_internal(FILE *dest, const char *prefix, const char *format, va_
void apk_out_fmt(struct apk_out *out, const char *prefix, const char *format, ...)
{
va_list va;
va_start(va, format);
log_internal(prefix ? out->err : out->out, prefix, format, va);
out->last_change++;
va_end(va);
if (prefix != APK_OUT_LOG_ONLY) {
va_start(va, format);
log_internal(prefix ? out->err : out->out, prefix, format, va);
out->last_change++;
va_end(va);
}
if (out->log) {
va_start(va, format);
log_internal(out->log, prefix, format, va);
va_end(va);
}
}
void apk_out_log_argv(struct apk_out *out, char **argv)
{
char when[32];
struct tm tm;
time_t now = time(NULL);
if (!out->log) return;
fprintf(out->log, "\nRunning `");
for (int i = 0; argv[i]; ++i) {
fprintf(out->log, "%s%s", argv[i], argv[i+1] ? " " : "");
}
gmtime_r(&now, &tm);
strftime(when, sizeof(when), "%Y-%m-%d %H:%M:%S", &tm);
fprintf(out->log, "` at %s\n", when);
}
void apk_print_progress(struct apk_progress *p, size_t done, size_t total)