From: Karel Zak Date: Tue, 3 Dec 2024 17:56:41 +0000 (+0100) Subject: libmount: read all types of kernel messages X-Git-Tag: v2.42-start~99 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=33c42f5b1728585c012f01121a6126e845e8e68b;p=thirdparty%2Futil-linux.git libmount: read all types of kernel messages Previously, libmount only read error messages from fsopen() file descriptor. This commit improves the library to read all messages and keep them in their original format (" ") in the library mount context. Applications can now read all messages by using mnt_context_get_mesgs(). Furthermore, private functions have been implemented to include new library-specific messages in the log. Currently, these messages are only managed in mnt_context_get_excode(), but it would be beneficial to relocate them to the appropriate locations where errors are triggered. In the future, mnt_context_get_excode() should only be utilized by basic applications that require an one error message. For more critical purposes (e.g. mount(8)), it will be recommended to utilize the messages array. The public function mnt_context_get_excode() has been modified to use the new functionality and provide messages in a backwardly compatible way. Signed-off-by: Karel Zak --- diff --git a/libmount/docs/libmount-sections.txt b/libmount/docs/libmount-sections.txt index 0b4adb595..02158ff89 100644 --- a/libmount/docs/libmount-sections.txt +++ b/libmount/docs/libmount-sections.txt @@ -107,6 +107,8 @@ mnt_context_set_target mnt_context_set_target_ns mnt_context_set_target_prefix mnt_context_set_user_mflags +mnt_context_get_mesgs +mnt_context_get_nmesgs mnt_context_strerror mnt_context_switch_ns mnt_context_switch_origin_ns diff --git a/libmount/src/context.c b/libmount/src/context.c index 565825ca5..a3bc33ab9 100644 --- a/libmount/src/context.c +++ b/libmount/src/context.c @@ -45,6 +45,7 @@ #include #include "mount-api-utils.h" +#include "strv.h" /** * mnt_new_context: @@ -2716,54 +2717,73 @@ void mnt_context_syscall_reset_status(struct libmnt_context *cxt) cxt->syscall_status = 0; cxt->syscall_name = NULL; - free(cxt->errmsg); - cxt->errmsg = NULL; + mnt_context_reset_mesgs(cxt); } -int mnt_context_set_errmsg(struct libmnt_context *cxt, const char *msg) +void mnt_context_reset_mesgs(struct libmnt_context *cxt) { - char *p = NULL; - - if (msg) { - p = strdup(msg); - if (!p) - return -ENOMEM; - } - - free(cxt->errmsg); - cxt->errmsg = p; - - return 0; + DBG(CXT, ul_debug("reset messages")); + strv_free(cxt->mesgs); + cxt->mesgs = NULL; } -int mnt_context_append_errmsg(struct libmnt_context *cxt, const char *msg) +int mnt_context_append_mesg(struct libmnt_context *cxt, const char *msg) { - if (cxt->errmsg) { - int rc = strappend(&cxt->errmsg, "; "); - if (rc) - return rc; - } - - return strappend(&cxt->errmsg, msg); + return strv_extend(&cxt->mesgs, msg); } -int mnt_context_sprintf_errmsg(struct libmnt_context *cxt, const char *msg, ...) +int mnt_context_sprintf_mesg(struct libmnt_context *cxt, const char *msg, ...) { int rc; va_list ap; - char *p = NULL; va_start(ap, msg); - rc = vasprintf(&p, msg, ap); + rc = strv_extendv(&cxt->mesgs, msg, ap); va_end(ap); - if (rc < 0 || !p) - return rc; + return rc; +} - free(cxt->errmsg); - cxt->errmsg = p; +/** + * mnt_context_get_nmesgs: + * @cxt: mount context + * @type: type of message (see fsopen() man page) or zero for all types + * + * Returns: number of messages + * + * Since: 2.41 + */ +size_t mnt_context_get_nmesgs(struct libmnt_context *cxt, char type) +{ + size_t n; + char **s; - return 0; + if (!cxt || !cxt->mesgs) + return 0; + + n = strv_length(cxt->mesgs); + if (n && type) { + n = 0; + STRV_FOREACH(s, cxt->mesgs) { + if (*s && **s == type) + n++; + } + } + + return n; +} + +/** + * mnt_context_get_mesgs: + * @cxt: mount context + * + * Returns: NULL terminated array of messages or NULL + * + * Since: 2.41 + */ +char **mnt_context_get_mesgs(struct libmnt_context *cxt) +{ + return cxt ? cxt->mesgs : NULL; } /** diff --git a/libmount/src/context_mount.c b/libmount/src/context_mount.c index c64e735da..76b24cd84 100644 --- a/libmount/src/context_mount.c +++ b/libmount/src/context_mount.c @@ -20,6 +20,7 @@ #include "mountP.h" #include "strutils.h" +#include "strv.h" #if defined(HAVE_SMACK) static int is_option(const char *name, const char *const *names) @@ -1445,6 +1446,31 @@ done: return rc; } +static void join_err_mesgs(struct libmnt_context *cxt, char *buf, size_t bufsz) +{ + char **s; + int n = 0; + + if (!cxt || !buf || strv_isempty(cxt->mesgs)) + return; + + STRV_FOREACH(s, cxt->mesgs) { + size_t len; + + if (!bufsz) + break; + if (!startswith(*s, "e ")) + continue; + if (n) { + len = xstrncpy(buf, "; ", bufsz); + buf += len, bufsz -= len; + } + len = xstrncpy(buf, (*s) + 2, bufsz); + buf += len, bufsz -= len; + n++; + } +} + int mnt_context_get_mount_excode( struct libmnt_context *cxt, int rc, @@ -1490,8 +1516,10 @@ int mnt_context_get_mount_excode( mnt_context_get_user_mflags(cxt, &uflags); /* userspace flags */ if (!mnt_context_syscall_called(cxt)) { - if (buf && cxt->errmsg) { - xstrncpy(buf, cxt->errmsg, bufsz); + + /* libmount errors already added to context log */ + if (buf && mnt_context_get_nmesgs(cxt, 'e')) { + join_err_mesgs(cxt, buf, bufsz); return MNT_EX_USAGE; } @@ -1634,16 +1662,20 @@ int mnt_context_get_mount_excode( */ syserr = mnt_context_get_syscall_errno(cxt); - if (buf && cxt->errmsg) { - if (cxt->syscall_name) - snprintf(buf, bufsz, _("%s system call failed: %s"), - cxt->syscall_name, cxt->errmsg); - else - xstrncpy(buf, cxt->errmsg, bufsz); + /* Error with already generated messages (by kernel or libmount) */ + if (buf && mnt_context_get_nmesgs(cxt, 'e')) { + if (cxt->syscall_name) { + size_t len = snprintf(buf, bufsz, + _("%s system call failed: "), + cxt->syscall_name); + join_err_mesgs(cxt, buf + len, bufsz - len); + } else + join_err_mesgs(cxt, buf, bufsz); return MNT_EX_FAIL; } + /* Classic mount(2) errors */ switch(syserr) { case EPERM: if (!buf) diff --git a/libmount/src/hook_loopdev.c b/libmount/src/hook_loopdev.c index 65d0f739e..4f831e0d8 100644 --- a/libmount/src/hook_loopdev.c +++ b/libmount/src/hook_loopdev.c @@ -281,7 +281,8 @@ static int setup_loopdev(struct libmnt_context *cxt, DBG(LOOP, ul_debugobj(cxt, "node lost")); dev_t devno = loopcxt_get_devno(&lc); - mnt_context_sprintf_errmsg(cxt, _("device node %s (%u:%u) is lost"), + /* TRANSLATORS: Do not translate "e ". It is a message classifier. */ + mnt_context_sprintf_mesg(cxt, _("e device node %s (%u:%u) is lost"), loopcxt_get_device(&lc), major(devno), minor(devno)); rc = -EINVAL; } diff --git a/libmount/src/hook_mount.c b/libmount/src/hook_mount.c index 7622cc863..a2a4aa636 100644 --- a/libmount/src/hook_mount.c +++ b/libmount/src/hook_mount.c @@ -70,8 +70,6 @@ static void save_fd_messages(struct libmnt_context *cxt, int fd) uint8_t buf[BUFSIZ]; int rc; - mnt_context_set_errmsg(cxt, NULL); - while ((rc = read(fd, buf, sizeof(buf) - 1)) != -1) { if (rc == 0) @@ -82,10 +80,7 @@ static void save_fd_messages(struct libmnt_context *cxt, int fd) buf[rc] = '\0'; DBG(CXT, ul_debug("message from kernel: \"%*s\"", rc, buf)); - - if (rc < 3 || strncmp((char *) buf, "e ", 2) != 0) - continue; - mnt_context_append_errmsg(cxt, ((char *) buf) + 2); + mnt_context_append_mesg(cxt, (char *) buf); } } @@ -96,11 +91,12 @@ static void hookset_set_syscall_status(struct libmnt_context *cxt, mnt_context_syscall_save_status(cxt, name, x); - if (!x) { - api = get_sysapi(cxt); - if (api && api->fd_fs >= 0) - save_fd_messages(cxt, api->fd_fs); - } + if (!x) + mnt_context_reset_mesgs(cxt); /* reset om error */ + + api = get_sysapi(cxt); + if (api && api->fd_fs >= 0) + save_fd_messages(cxt, api->fd_fs); } /* diff --git a/libmount/src/libmount.h.in b/libmount/src/libmount.h.in index 0a2d82199..0300584ec 100644 --- a/libmount/src/libmount.h.in +++ b/libmount/src/libmount.h.in @@ -886,6 +886,9 @@ extern int mnt_context_syscall_called(struct libmnt_context *cxt); extern int mnt_context_get_syscall_errno(struct libmnt_context *cxt); +extern size_t mnt_context_get_nmesgs(struct libmnt_context *cxt, char type); +extern char **mnt_context_get_mesgs(struct libmnt_context *cxt); + extern int mnt_context_strerror(struct libmnt_context *cxt, char *buf, size_t bufsiz) __ul_attribute__((deprecated)); diff --git a/libmount/src/libmount.sym b/libmount/src/libmount.sym index 2b6b12d5c..ed5acbb2f 100644 --- a/libmount/src/libmount.sym +++ b/libmount/src/libmount.sym @@ -381,3 +381,8 @@ MOUNT_2_40 { mnt_unref_lock; mnt_monitor_veil_kernel; } MOUNT_2_39; + +MOUNT_2_41 { + mnt_context_get_nmesgs; + mnt_context_get_mesgs; +} MOUNT_2_40; diff --git a/libmount/src/mountP.h b/libmount/src/mountP.h index 893f9e729..365a6e0f0 100644 --- a/libmount/src/mountP.h +++ b/libmount/src/mountP.h @@ -432,7 +432,8 @@ struct libmnt_context int syscall_status; /* 1: not called yet, 0: success, <0: -errno */ const char *syscall_name; /* failed syscall name */ - char *errmsg; /* library or kernel message */ + + char **mesgs; /* library or kernel messages (NULL terminated array) */ struct libmnt_ns ns_orig; /* original namespace */ struct libmnt_ns ns_tgt; /* target namespace */ @@ -627,9 +628,9 @@ extern int mnt_context_update_tabs(struct libmnt_context *cxt); extern int mnt_context_umount_setopt(struct libmnt_context *cxt, int c, char *arg); extern int mnt_context_mount_setopt(struct libmnt_context *cxt, int c, char *arg); -extern int mnt_context_set_errmsg(struct libmnt_context *cxt, const char *msg); -extern int mnt_context_append_errmsg(struct libmnt_context *cxt, const char *msg); -extern int mnt_context_sprintf_errmsg(struct libmnt_context *cxt, const char *msg, ...); +extern void mnt_context_reset_mesgs(struct libmnt_context *cxt); +extern int mnt_context_append_mesg(struct libmnt_context *cxt, const char *msg); +extern int mnt_context_sprintf_mesg(struct libmnt_context *cxt, const char *msg, ...); extern int mnt_context_propagation_only(struct libmnt_context *cxt) __attribute__((nonnull));