/* SPDX-License-Identifier: MIT */ /* * Description: test open with fixed-file support * */ #include #include #include #include #include #include #include "liburing.h" static int create_file(const char *file, size_t size, int byte) { ssize_t ret; char *buf; int fd; buf = malloc(size); memset(buf, byte, size); fd = open(file, O_WRONLY | O_CREAT, 0644); if (fd < 0) { perror("open file"); return 1; } ret = write(fd, buf, size); close(fd); return ret != size; } static int test_openat2_fixed_file(struct io_uring *ring, const char *path1, const char *path2) { struct io_uring_cqe *cqe; struct io_uring_sqe *sqe; struct open_how how = { .flags = O_RDONLY }; int ret; int fds[2] = { -1, -1 }; unsigned char byte1 = 0, byte2 = 0; int i; ret = io_uring_register_files(ring, fds, 2); sqe = io_uring_get_sqe(ring); io_uring_prep_openat2_fixed_file(sqe, -1, path1, &how, 0); sqe->flags |= IOSQE_IO_LINK; sqe = io_uring_get_sqe(ring); io_uring_prep_openat2_fixed_file(sqe, -1, path2, &how, 1); sqe->flags |= IOSQE_IO_LINK; ret = io_uring_submit(ring); if (ret != 2) { fprintf(stderr, "sqe submit failed: %d\n", ret); goto err; } for (i = 0; i < 2; i++) { ret = io_uring_wait_cqe(ring, &cqe); if (ret < 0) { fprintf(stderr, "wait completion %d\n", ret); goto err; } ret = cqe->res; if (ret < 0) { fprintf(stderr, "operation %d failed: %d\n", i, ret); goto err; } io_uring_cqe_seen(ring, cqe); } sqe = io_uring_get_sqe(ring); io_uring_prep_read(sqe, 0, &byte1, 1, 0); sqe->flags |= IOSQE_FIXED_FILE; sqe = io_uring_get_sqe(ring); io_uring_prep_read(sqe, 1, &byte2, 1, 0); sqe->flags |= IOSQE_FIXED_FILE; ret = io_uring_submit(ring); if (ret != 2) { fprintf(stderr, "sqe submit failed: %d\n", ret); goto err; } for (i = 0; i < 2; i++) { ret = io_uring_wait_cqe(ring, &cqe); if (ret < 0) { fprintf(stderr, "wait completion %d\n", ret); goto err; } ret = cqe->res; if (ret < 0) { fprintf(stderr, "operation %d failed: %d\n", i, ret); goto err; } io_uring_cqe_seen(ring, cqe); } if (byte1 != 0x11 || byte2 != 0x22) { fprintf(stderr, "bytes did not have expected values: %x %x\n", (unsigned)byte1, (unsigned)byte2); ret = -1; goto err; } err: return ret; } int main(int argc, char *argv[]) { struct io_uring ring; const char *path1, *path2; int ret; ret = io_uring_queue_init(8, &ring, 0); if (ret) { fprintf(stderr, "ring setup failed\n"); return 1; } path1 = "/tmp/.open.close.1"; path2 = "/tmp/.open.close.2"; if (create_file(path1, 4096, 0x11) || create_file(path2, 4096, 0x22)) { fprintf(stderr, "file create failed\n"); return 1; } ret = test_openat2_fixed_file(&ring, path1, path2); if (ret < 0) { if (ret == -EINVAL) { fprintf(stdout, "openat2 not supported, skipping\n"); goto done; } fprintf(stderr, "test_openat2 failed: %d\n", ret); goto err; } done: unlink(path1); unlink(path2); return 0; err: unlink(path1); unlink(path2); return 1; }