#define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #define bail(msg) \ do { printf("mount_to_symlink: %s: %m\n", msg); exit(1); } while (0) int is_symlink(const char *path) { struct stat stat = {}; if (lstat(path, &stat) < 0) bail("lstat()"); return S_ISLNK(stat.st_mode); } int main(int argc, char **argv) { struct stat stat = {}; char *src, *dst, *src_fdpath, *dst_fdpath; int src_fd, dst_fd; if (argc != 3) bail("usage: mount_to_symlink "); src_fdpath = src = argv[1]; dst_fdpath = dst = argv[2]; if (is_symlink(src)) { // open source fd src_fd = open(src, O_PATH | O_CLOEXEC | O_NOFOLLOW); if (src_fd < 0) bail("open(, O_PATH|O_NOFOLLOW)"); // construct fd path asprintf(&src_fdpath, "/proc/self/fd/%d", src_fd); } if (is_symlink(dst)) { // open target fd dst_fd = open(dst, O_PATH | O_CLOEXEC | O_NOFOLLOW); if (dst_fd < 0) bail("open(, O_PATH|O_NOFOLLOW)"); // construct fd path asprintf(&dst_fdpath, "/proc/self/fd/%d", dst_fd); } // try to mount mount(src_fdpath, dst_fdpath, "", MS_BIND, ""); printf("mount(%s, %s, MS_BIND) = %m (%d)\n", src, dst, -errno); return 0; }