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
#include <sys/wait.h>
#include "mount-api-utils.h"
+#include "strv.h"
/**
* mnt_new_context:
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;
}
/**
#include "mountP.h"
#include "strutils.h"
+#include "strv.h"
#if defined(HAVE_SMACK)
static int is_option(const char *name, const char *const *names)
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,
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;
}
*/
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)
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;
}
uint8_t buf[BUFSIZ];
int rc;
- mnt_context_set_errmsg(cxt, NULL);
-
while ((rc = read(fd, buf, sizeof(buf) - 1)) != -1) {
if (rc == 0)
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);
}
}
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);
}
/*
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));
mnt_unref_lock;
mnt_monitor_veil_kernel;
} MOUNT_2_39;
+
+MOUNT_2_41 {
+ mnt_context_get_nmesgs;
+ mnt_context_get_mesgs;
+} MOUNT_2_40;
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 */
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));