unlink.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. #include "../config-host.h"
  2. /* SPDX-License-Identifier: MIT */
  3. /*
  4. * Description: run various unlink tests
  5. *
  6. */
  7. #include <errno.h>
  8. #include <stdio.h>
  9. #include <unistd.h>
  10. #include <stdlib.h>
  11. #include <string.h>
  12. #include <fcntl.h>
  13. #include <sys/stat.h>
  14. #include "liburing.h"
  15. static int test_rmdir(struct io_uring *ring)
  16. {
  17. struct io_uring_cqe *cqe;
  18. struct io_uring_sqe *sqe;
  19. char buf[32];
  20. int ret;
  21. sprintf(buf, ".tmp.dir.%d", getpid());
  22. if (mkdir(buf, 0755) < 0) {
  23. perror("mkdir");
  24. return 1;
  25. }
  26. sqe = io_uring_get_sqe(ring);
  27. if (!sqe) {
  28. fprintf(stderr, "get sqe failed\n");
  29. goto err;
  30. }
  31. io_uring_prep_unlink(sqe, buf, AT_REMOVEDIR);
  32. ret = io_uring_submit(ring);
  33. if (ret <= 0) {
  34. fprintf(stderr, "sqe submit failed: %d\n", ret);
  35. goto err;
  36. }
  37. ret = io_uring_wait_cqe(ring, &cqe);
  38. if (ret < 0) {
  39. fprintf(stderr, "wait completion %d\n", ret);
  40. goto err;
  41. }
  42. ret = cqe->res;
  43. io_uring_cqe_seen(ring, cqe);
  44. if (!ret) {
  45. struct stat sb;
  46. if (!stat(buf, &sb)) {
  47. fprintf(stderr, "dir unlinked but still there\n");
  48. goto err;
  49. }
  50. }
  51. unlink(buf);
  52. return ret;
  53. err:
  54. unlink(buf);
  55. return 1;
  56. }
  57. static int test_unlink_badaddr(struct io_uring *ring)
  58. {
  59. const char *old = (const char *) (uintptr_t) 0x1234;
  60. struct io_uring_cqe *cqe;
  61. struct io_uring_sqe *sqe;
  62. int ret;
  63. sqe = io_uring_get_sqe(ring);
  64. if (!sqe) {
  65. fprintf(stderr, "get sqe failed\n");
  66. goto err;
  67. }
  68. io_uring_prep_unlink(sqe, old, 0);
  69. ret = io_uring_submit(ring);
  70. if (ret <= 0) {
  71. fprintf(stderr, "sqe submit failed: %d\n", ret);
  72. goto err;
  73. }
  74. ret = io_uring_wait_cqe(ring, &cqe);
  75. if (ret < 0) {
  76. fprintf(stderr, "wait completion %d\n", ret);
  77. goto err;
  78. }
  79. ret = cqe->res;
  80. io_uring_cqe_seen(ring, cqe);
  81. return ret;
  82. err:
  83. return 1;
  84. }
  85. static int test_unlink(struct io_uring *ring, const char *old)
  86. {
  87. struct io_uring_cqe *cqe;
  88. struct io_uring_sqe *sqe;
  89. int ret;
  90. sqe = io_uring_get_sqe(ring);
  91. if (!sqe) {
  92. fprintf(stderr, "get sqe failed\n");
  93. goto err;
  94. }
  95. io_uring_prep_unlink(sqe, old, 0);
  96. ret = io_uring_submit(ring);
  97. if (ret <= 0) {
  98. fprintf(stderr, "sqe submit failed: %d\n", ret);
  99. goto err;
  100. }
  101. ret = io_uring_wait_cqe(ring, &cqe);
  102. if (ret < 0) {
  103. fprintf(stderr, "wait completion %d\n", ret);
  104. goto err;
  105. }
  106. ret = cqe->res;
  107. io_uring_cqe_seen(ring, cqe);
  108. return ret;
  109. err:
  110. return 1;
  111. }
  112. static int stat_file(const char *buf)
  113. {
  114. struct stat sb;
  115. if (!stat(buf, &sb))
  116. return 0;
  117. return errno;
  118. }
  119. int main(int argc, char *argv[])
  120. {
  121. struct io_uring ring;
  122. char buf[32] = "./XXXXXX";
  123. int ret;
  124. if (argc > 1)
  125. return 0;
  126. ret = io_uring_queue_init(1, &ring, 0);
  127. if (ret) {
  128. fprintf(stderr, "ring setup failed: %d\n", ret);
  129. return 1;
  130. }
  131. ret = mkstemp(buf);
  132. if (ret < 0) {
  133. perror("mkstemp");
  134. return 1;
  135. }
  136. close(ret);
  137. if (stat_file(buf) != 0) {
  138. perror("stat");
  139. return 1;
  140. }
  141. ret = test_unlink(&ring, buf);
  142. if (ret < 0) {
  143. if (ret == -EBADF || ret == -EINVAL) {
  144. fprintf(stdout, "Unlink not supported, skipping\n");
  145. unlink(buf);
  146. return 0;
  147. }
  148. fprintf(stderr, "rename: %s\n", strerror(-ret));
  149. goto err;
  150. } else if (ret)
  151. goto err;
  152. ret = stat_file(buf);
  153. if (ret != ENOENT) {
  154. fprintf(stderr, "stat got %s\n", strerror(ret));
  155. return 1;
  156. }
  157. ret = test_unlink(&ring, "/3/2/3/1/z/y");
  158. if (ret != -ENOENT) {
  159. fprintf(stderr, "invalid unlink got %s\n", strerror(-ret));
  160. return 1;
  161. }
  162. ret = test_unlink_badaddr(&ring);
  163. if (ret != -EFAULT) {
  164. fprintf(stderr, "badaddr unlink got %s\n", strerror(-ret));
  165. return 1;
  166. }
  167. ret = test_rmdir(&ring);
  168. if (ret) {
  169. fprintf(stderr, "rmdir failed: %s\n", strerror(-ret));
  170. return 1;
  171. }
  172. return 0;
  173. err:
  174. unlink(buf);
  175. return 1;
  176. }