diff options
Diffstat (limited to 'libmount/src/hook_mount.c')
-rw-r--r-- | libmount/src/hook_mount.c | 84 |
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; |