/* * PoC for using new mount API for mount.cifs */ #include #include #include #include #include /* * For MS_*, MNT_* constants */ #include /* * For FSCONFIG_*, FSMOUNT_*, MOVE_* constants * * TODO: need to add configure check for header availability */ #include /* * For AT_* constants */ #include /* * The new mount API syscalls have currently no wrappers in * glibc. Call them via syscall(). * * Wrap in #ifdef to be future-proof once they eventually get wrappers * * TODO: add configure checks for fsopen symbol -> HAVE_FSOPEN */ #ifndef HAVE_FSOPEN #include int fsopen(const char *fsname, unsigned int flags) { return syscall(SYS_fsopen, fsname, flags); } int fsmount(int fd, unsigned int flags, unsigned int mount_attrs) { return syscall(SYS_fsmount, fd, flags, mount_attrs); } int fsconfig(int fd, unsigned int cmd, const char *key, const void *value, int aux) { return syscall(SYS_fsconfig, fd, cmd, key, value, aux); } int move_mount(int from_dirfd, const char *from_pathname, int to_dirfd, const char *to_pathname, unsigned int flags) { return syscall(SYS_move_mount, from_dirfd, from_pathname, to_dirfd, to_pathname, flags); } #endif /* * To get the kernel log emitted after a call, simply read the context fd * * "e " * An error message string was logged. * * "i " * An informational message string was logged. * * "w " * An warning message string was logged. * * Messages are removed from the queue as they're read. * */ void print_context_log(int fd) { char buf[512]; ssize_t rc; int first = 1; while (1) { memset(buf, 0, sizeof(buf)); rc = read(fd, buf, sizeof(buf)-2); if (rc == 0 || (rc < 0 && errno == ENODATA)) { errno = 0; break; } else if (rc < 0) { perror("read"); break; } if (first) { printf("kernel mount errors:\n"); first = 0; } printf("%s", buf); } } #define CHECK(x) \ do { \ if ((x) < 0) { \ perror(#x); \ exit(1); \ } \ } while (0) #define CHECK_AND_LOG(fd, x) \ do { \ if ((x) < 0) { \ perror(#x); \ print_context_log(fd); \ exit(1); \ } \ } while (0) int main(void) { int sfd; int mfd; /* * Converting following old-style mount syscall to new mount api * * mount( * "//192.168.2.110/data", * "/mnt/test", * "cifs", * 0, * "ip=192.168.2.110,unc=\\\\192.168.2.110\\data,vers=3.0,user=administrator,pass=my-pass" * ) * */ CHECK(sfd = fsopen("cifs", 0)); CHECK_AND_LOG(sfd, fsconfig(sfd, FSCONFIG_SET_STRING, "source", "//192.168.2.110/data", 0)); CHECK_AND_LOG(sfd, fsconfig(sfd, FSCONFIG_SET_STRING, "ip", "192.168.2.110", 0)); CHECK_AND_LOG(sfd, fsconfig(sfd, FSCONFIG_SET_STRING, "unc", "\\\\192.168.2.110\\data", 0)); CHECK_AND_LOG(sfd, fsconfig(sfd, FSCONFIG_SET_STRING, "vers", "3.0", 0)); CHECK_AND_LOG(sfd, fsconfig(sfd, FSCONFIG_SET_STRING, "user", "administrator", 0)); CHECK_AND_LOG(sfd, fsconfig(sfd, FSCONFIG_SET_STRING, "pass", "my-pass", 0)); CHECK_AND_LOG(sfd, fsconfig(sfd, FSCONFIG_CMD_CREATE, NULL, NULL, 0)); CHECK_AND_LOG(sfd, (mfd = fsmount(sfd, FSMOUNT_CLOEXEC, 0))); CHECK(move_mount(mfd, "", AT_FDCWD, "/mnt/test", MOVE_MOUNT_F_EMPTY_PATH)); return 0; }