summaryrefslogtreecommitdiffstats
path: root/libmount/src/hook_mount.c
diff options
context:
space:
mode:
Diffstat (limited to 'libmount/src/hook_mount.c')
-rw-r--r--libmount/src/hook_mount.c84
1 files changed, 65 insertions, 19 deletions
diff --git a/libmount/src/hook_mount.c b/libmount/src/hook_mount.c
index dc3dfa7..f0cc381 100644
--- a/libmount/src/hook_mount.c
+++ b/libmount/src/hook_mount.c
@@ -65,6 +65,42 @@ static void close_sysapi_fds(struct libmnt_sysapi *api)
api->fd_tree = api->fd_fs = -1;
}
+static void save_fd_messages(struct libmnt_context *cxt, int fd)
+{
+ uint8_t buf[BUFSIZ];
+ int rc;
+
+ free(cxt->syscall_errmsg);
+ cxt->syscall_errmsg = NULL;
+
+ while ((rc = read(fd, buf, sizeof(buf))) != -1) {
+ if (rc > 0 && buf[rc - 1] == '\n')
+ buf[rc - 1] = '\0';
+ DBG(CXT, ul_debug("message from kernel: \"%*s\"", rc, buf));
+
+ if (rc < 3 || strncmp((char *) buf, "e ", 2) != 0)
+ continue;
+ if (cxt->syscall_errmsg)
+ strappend(&cxt->syscall_errmsg, "; ");
+
+ strappend(&cxt->syscall_errmsg, ((char *) buf) + 2);
+ }
+}
+
+static void hookset_set_syscall_status(struct libmnt_context *cxt,
+ const char *name, int x)
+{
+ struct libmnt_sysapi *api;
+
+ set_syscall_status(cxt, name, x);
+
+ if (!x) {
+ api = get_sysapi(cxt);
+ if (api && api->fd_fs >= 0)
+ save_fd_messages(cxt, api->fd_fs);
+ }
+}
+
/*
* This hookset uses 'struct libmnt_sysapi' (mountP.h) as hookset data.
*/
@@ -122,26 +158,33 @@ static inline int fsconfig_set_value(
const char *name, const char *value)
{
int rc;
- char *p = NULL;
+ char *s = NULL;
+ /* "\," is a way to use comma in values, let's remove \ escape */
if (value && strstr(value, "\\,")) {
- p = strdup(value);
- if (!p)
- return -EINVAL;
+ char *x, *p;
- strrem(p, '\\');
- value = p;
+ s = strdup(value);
+ if (!s)
+ return -EINVAL;
+ for (x = p = s; *x; p++, x++) {
+ if (*x == '\\' && *(x + 1) == ',')
+ x++;
+ *p = *x;
+ }
+ *p = '\0';
+ value = s;
}
DBG(HOOK, ul_debugobj(hs, " fsconfig(name=\"%s\" value=\"%s\")", name,
value ? : ""));
if (value) {
rc = fsconfig(fd, FSCONFIG_SET_STRING, name, value, 0);
- free(p);
+ free(s);
} else
rc = fsconfig(fd, FSCONFIG_SET_FLAG, name, NULL, 0);
- set_syscall_status(cxt, "fsconfig", rc == 0);
+ hookset_set_syscall_status(cxt, "fsconfig", rc == 0);
return rc;
}
@@ -181,6 +224,9 @@ static int configure_superblock(struct libmnt_context *cxt,
/* Ignore VFS flags, userspace and external options */
continue;
+ if (!value && mnt_opt_is_sepnodata(opt))
+ value = ""; /* force use the value as string */
+
rc = fsconfig_set_value(cxt, hs, fd, name, value);
if (rc != 0)
goto done;
@@ -206,7 +252,7 @@ static int open_fs_configuration_context(struct libmnt_context *cxt,
DBG(HOOK, ul_debug(" fsopen(%s)", type));
api->fd_fs = fsopen(type, FSOPEN_CLOEXEC);
- set_syscall_status(cxt, "fsopen", api->fd_fs >= 0);
+ hookset_set_syscall_status(cxt, "fsopen", api->fd_fs >= 0);
if (api->fd_fs < 0)
return -errno;
api->is_new_fs = 1;
@@ -245,7 +291,7 @@ static int open_mount_tree(struct libmnt_context *cxt, const char *path, unsigne
oflg & OPEN_TREE_CLONE ? " clone" : "",
oflg & AT_RECURSIVE ? " recursive" : ""));
fd = open_tree(AT_FDCWD, path, oflg);
- set_syscall_status(cxt, "open_tree", fd >= 0);
+ hookset_set_syscall_status(cxt, "open_tree", fd >= 0);
return fd;
}
@@ -285,19 +331,19 @@ static int hook_create_mount(struct libmnt_context *cxt,
DBG(HOOK, ul_debugobj(hs, "init FS"));
rc = fsconfig(api->fd_fs, FSCONFIG_SET_STRING, "source", src, 0);
- set_syscall_status(cxt, "fsconfig", rc == 0);
+ hookset_set_syscall_status(cxt, "fsconfig", rc == 0);
if (!rc)
rc = configure_superblock(cxt, hs, api->fd_fs, 0);
if (!rc) {
DBG(HOOK, ul_debugobj(hs, "create FS"));
rc = fsconfig(api->fd_fs, FSCONFIG_CMD_CREATE, NULL, NULL, 0);
- set_syscall_status(cxt, "fsconfig", rc == 0);
+ hookset_set_syscall_status(cxt, "fsconfig", rc == 0);
}
if (!rc) {
api->fd_tree = fsmount(api->fd_fs, FSMOUNT_CLOEXEC, 0);
- set_syscall_status(cxt, "fsmount", api->fd_tree >= 0);
+ hookset_set_syscall_status(cxt, "fsmount", api->fd_tree >= 0);
if (api->fd_tree < 0)
rc = -errno;
}
@@ -346,7 +392,7 @@ static int hook_reconfigure_mount(struct libmnt_context *cxt,
if (api->fd_fs < 0) {
api->fd_fs = fspick(api->fd_tree, "", FSPICK_EMPTY_PATH |
FSPICK_NO_AUTOMOUNT);
- set_syscall_status(cxt, "fspick", api->fd_fs >= 0);
+ hookset_set_syscall_status(cxt, "fspick", api->fd_fs >= 0);
if (api->fd_fs < 0)
return -errno;
}
@@ -355,7 +401,7 @@ static int hook_reconfigure_mount(struct libmnt_context *cxt,
if (!rc) {
DBG(HOOK, ul_debugobj(hs, "re-configurate FS"));
rc = fsconfig(api->fd_fs, FSCONFIG_CMD_RECONFIGURE, NULL, NULL, 0);
- set_syscall_status(cxt, "fsconfig", rc == 0);
+ hookset_set_syscall_status(cxt, "fsconfig", rc == 0);
}
DBG(HOOK, ul_debugobj(hs, "reconf FS done [rc=%d]", rc));
@@ -393,7 +439,7 @@ static int set_vfsflags(struct libmnt_context *cxt,
errno = 0;
rc = mount_setattr(api->fd_tree, "", callflags, &attr, sizeof(attr));
- set_syscall_status(cxt, "mount_setattr", rc == 0);
+ hookset_set_syscall_status(cxt, "mount_setattr", rc == 0);
if (rc && errno == EINVAL)
return -MNT_ERR_APPLYFLAGS;
@@ -485,7 +531,7 @@ static int hook_set_propagation(struct libmnt_context *cxt,
(uint64_t) attr.propagation));
rc = mount_setattr(api->fd_tree, "", flgs, &attr, sizeof(attr));
- set_syscall_status(cxt, "mount_setattr", rc == 0);
+ hookset_set_syscall_status(cxt, "mount_setattr", rc == 0);
if (rc && errno == EINVAL)
return -MNT_ERR_APPLYFLAGS;
@@ -527,7 +573,7 @@ static int hook_attach_target(struct libmnt_context *cxt,
}
rc = move_mount(api->fd_tree, "", AT_FDCWD, target, MOVE_MOUNT_F_EMPTY_PATH);
- set_syscall_status(cxt, "move_mount", rc == 0);
+ hookset_set_syscall_status(cxt, "move_mount", rc == 0);
return rc == 0 ? 0 : -errno;
}
@@ -613,7 +659,7 @@ static int init_sysapi(struct libmnt_context *cxt,
else if (!fsopen_is_supported()) {
errno = ENOSYS;
rc = -errno;
- set_syscall_status(cxt, "fsopen", rc == 0);
+ hookset_set_syscall_status(cxt, "fsopen", rc == 0);
}
if (rc < 0)
goto fail;