#include #include #include #include static int failures; static int successes; #define CHECK(ret) \ do \ if ((ret) < 0) \ { \ printf ("error: %s:\n %m\n", #ret); \ ++failures; \ } \ else \ { \ printf ("success: %s\n", #ret); \ ++successes; \ } \ while (0) int main (void) { const char *const out_name = "linkat.out"; unlink (out_name); int fd = open (".", O_RDWR | O_TMPFILE, 0); if (fd < 0) err (1, "open"); int current_fd = open (".", O_RDONLY | O_DIRECTORY); if (current_fd < 0) err (1, "open (O_DIRECTORY)"); int proc_fd = open ("/proc/self/fd", O_RDONLY | O_DIRECTORY); if (proc_fd < 0) err (1, "open (O_DIRECTORY)"); CHECK (linkat (fd, "", AT_FDCWD, out_name, AT_EMPTY_PATH)); unlink (out_name); CHECK (linkat (fd, "", current_fd, out_name, AT_EMPTY_PATH)); unlink (out_name); char proc_name[100]; snprintf (proc_name, sizeof (proc_name), "/proc/self/fd/%d", fd); CHECK (linkat (AT_FDCWD, proc_name, AT_FDCWD, out_name, AT_SYMLINK_FOLLOW)); unlink (out_name); CHECK (linkat (AT_FDCWD, proc_name, current_fd, out_name, AT_SYMLINK_FOLLOW)); unlink (out_name); snprintf (proc_name, sizeof (proc_name), "%d", fd); CHECK (linkat (proc_fd, proc_name, AT_FDCWD, out_name, AT_SYMLINK_FOLLOW)); unlink (out_name); CHECK (linkat (proc_fd, proc_name, current_fd, out_name, AT_SYMLINK_FOLLOW)); unlink (out_name); printf ("successes: %d, failures: %d\n", successes, failures); return 0; }