test_io.cpp 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. #include <AK/Assertions.h>
  2. #include <AK/Types.h>
  3. #include <fcntl.h>
  4. #include <stdio.h>
  5. #include <sys/mman.h>
  6. #include <sys/stat.h>
  7. #include <unistd.h>
  8. #define EXPECT_ERROR_2(err, syscall, arg1, arg2) \
  9. do { \
  10. rc = syscall(arg1, arg2); \
  11. if (rc >= 0 || errno != err) { \
  12. fprintf(stderr, __FILE__ ":%d: Expected " #err ": " #syscall "(%p, %p), got rc=%d, errno=%d\n", __LINE__, (const void*)(arg1), (const void*)arg2, rc, errno); \
  13. } \
  14. } while (0)
  15. #define EXPECT_ERROR_3(err, syscall, arg1, arg2, arg3) \
  16. do { \
  17. rc = syscall(arg1, arg2, arg3); \
  18. if (rc >= 0 || errno != err) { \
  19. fprintf(stderr, __FILE__ ":%d: Expected " #err ": " #syscall "(%p, %p, %p), got rc=%d, errno=%d\n", __LINE__, (const void*)(arg1), (const void*)(arg2), (const void*)(arg3), rc, errno); \
  20. } \
  21. } while (0)
  22. void test_read_from_directory()
  23. {
  24. char buffer[BUFSIZ];
  25. int fd = open("/", O_DIRECTORY | O_RDONLY);
  26. ASSERT(fd >= 0);
  27. int rc;
  28. EXPECT_ERROR_3(EISDIR, read, fd, buffer, sizeof(buffer));
  29. rc = close(fd);
  30. ASSERT(rc == 0);
  31. }
  32. void test_write_to_directory()
  33. {
  34. char str[] = "oh frick";
  35. int fd = open("/", O_DIRECTORY | O_RDONLY);
  36. if (fd < 0)
  37. perror("open");
  38. ASSERT(fd >= 0);
  39. int rc;
  40. EXPECT_ERROR_3(EBADF, write, fd, str, sizeof(str));
  41. rc = close(fd);
  42. ASSERT(rc == 0);
  43. }
  44. void test_read_from_writeonly()
  45. {
  46. char buffer[BUFSIZ];
  47. int fd = open("/tmp/xxxx123", O_CREAT | O_WRONLY);
  48. ASSERT(fd >= 0);
  49. int rc;
  50. EXPECT_ERROR_3(EBADF, read, fd, buffer, sizeof(buffer));
  51. rc = close(fd);
  52. ASSERT(rc == 0);
  53. }
  54. void test_write_to_readonly()
  55. {
  56. char str[] = "hello";
  57. int fd = open("/tmp/abcd123", O_CREAT | O_RDONLY);
  58. ASSERT(fd >= 0);
  59. int rc;
  60. EXPECT_ERROR_3(EBADF, write, fd, str, sizeof(str));
  61. rc = close(fd);
  62. ASSERT(rc == 0);
  63. }
  64. void test_read_past_eof()
  65. {
  66. char buffer[BUFSIZ];
  67. int fd = open("/home/anon/myfile.txt", O_RDONLY);
  68. if (fd < 0)
  69. perror("open");
  70. ASSERT(fd >= 0);
  71. int rc;
  72. rc = lseek(fd, 9999, SEEK_SET);
  73. if (rc < 0)
  74. perror("lseek");
  75. rc = read(fd, buffer, sizeof(buffer));
  76. if (rc < 0)
  77. perror("read");
  78. if (rc > 0)
  79. fprintf(stderr, "read %d bytes past EOF\n", rc);
  80. rc = close(fd);
  81. ASSERT(rc == 0);
  82. }
  83. void test_ftruncate_readonly()
  84. {
  85. int fd = open("/tmp/trunctest", O_RDONLY | O_CREAT, 0666);
  86. ASSERT(fd >= 0);
  87. int rc;
  88. EXPECT_ERROR_2(EBADF, ftruncate, fd, 0);
  89. close(fd);
  90. }
  91. void test_ftruncate_negative()
  92. {
  93. int fd = open("/tmp/trunctest", O_RDWR | O_CREAT, 0666);
  94. ASSERT(fd >= 0);
  95. int rc;
  96. EXPECT_ERROR_2(EINVAL, ftruncate, fd, -1);
  97. close(fd);
  98. }
  99. void test_mmap_directory()
  100. {
  101. int fd = open("/tmp", O_RDONLY | O_DIRECTORY);
  102. ASSERT(fd >= 0);
  103. auto* ptr = mmap(nullptr, 4096, PROT_READ, MAP_FILE | MAP_SHARED, fd, 0);
  104. if (ptr != MAP_FAILED) {
  105. fprintf(stderr, "Boo! mmap() of a directory succeeded!\n");
  106. return;
  107. }
  108. if (errno != ENODEV) {
  109. fprintf(stderr, "Boo! mmap() of a directory gave errno=%d instead of ENODEV!\n", errno);
  110. return;
  111. }
  112. close(fd);
  113. }
  114. void test_tmpfs_read_past_end()
  115. {
  116. int fd = open("/tmp/x", O_RDWR | O_CREAT | O_TRUNC, 0600);
  117. ASSERT(fd >= 0);
  118. int rc = ftruncate(fd, 1);
  119. ASSERT(rc == 0);
  120. rc = lseek(fd, 4096, SEEK_SET);
  121. ASSERT(rc == 4096);
  122. char buffer[16];
  123. int nread = read(fd, buffer, sizeof(buffer));
  124. if (nread != 0) {
  125. fprintf(stderr, "Expected 0-length read past end of file in /tmp\n");
  126. }
  127. close(fd);
  128. }
  129. void test_procfs_read_past_end()
  130. {
  131. int fd = open("/proc/uptime", O_RDONLY);
  132. ASSERT(fd >= 0);
  133. int rc = lseek(fd, 4096, SEEK_SET);
  134. ASSERT(rc == 4096);
  135. char buffer[16];
  136. int nread = read(fd, buffer, sizeof(buffer));
  137. if (nread != 0) {
  138. fprintf(stderr, "Expected 0-length read past end of file in /proc\n");
  139. }
  140. close(fd);
  141. }
  142. void test_open_create_device()
  143. {
  144. int fd = open("/tmp/fakedevice", (O_RDWR | O_CREAT), (S_IFCHR | 0600));
  145. ASSERT(fd >= 0);
  146. struct stat st;
  147. if (fstat(fd, &st) < 0) {
  148. perror("stat");
  149. ASSERT_NOT_REACHED();
  150. }
  151. if (st.st_mode != 0100600) {
  152. fprintf(stderr, "Expected mode 0100600 after attempt to create a device node with open(O_CREAT), mode=%o\n", st.st_mode);
  153. }
  154. unlink("/tmp/fakedevice");
  155. close(fd);
  156. }
  157. void test_unlink_symlink()
  158. {
  159. int rc = symlink("/proc/2/foo", "/tmp/linky");
  160. if (rc < 0) {
  161. perror("symlink");
  162. ASSERT_NOT_REACHED();
  163. }
  164. rc = unlink("/tmp/linky");
  165. if (rc < 0) {
  166. perror("unlink");
  167. fprintf(stderr, "Expected unlink() of a symlink into an unreadable directory to succeed!\n");
  168. }
  169. }
  170. void test_eoverflow()
  171. {
  172. int fd = open("/tmp/x", O_RDWR);
  173. ASSERT(fd >= 0);
  174. int rc = lseek(fd, INT32_MAX, SEEK_SET);
  175. ASSERT(rc == INT32_MAX);
  176. char buffer[16];
  177. rc = read(fd, buffer, sizeof(buffer));
  178. if (rc >= 0 || errno != EOVERFLOW) {
  179. fprintf(stderr, "Expected EOVERFLOW when trying to read past INT32_MAX\n");
  180. }
  181. rc = write(fd, buffer, sizeof(buffer));
  182. if (rc >= 0 || errno != EOVERFLOW) {
  183. fprintf(stderr, "Expected EOVERFLOW when trying to write past INT32_MAX\n");
  184. }
  185. close(fd);
  186. }
  187. void test_rmdir_while_inside_dir()
  188. {
  189. int rc = mkdir("/home/anon/testdir", 0700);
  190. ASSERT(rc == 0);
  191. rc = chdir("/home/anon/testdir");
  192. ASSERT(rc == 0);
  193. rc = rmdir("/home/anon/testdir");
  194. ASSERT(rc == 0);
  195. int fd = open("x", O_CREAT | O_RDWR, 0600);
  196. if (fd >= 0 || errno != ENOENT) {
  197. fprintf(stderr, "Expected ENOENT when trying to create a file inside a deleted directory. Got %d with errno=%d\n", fd, errno);
  198. }
  199. rc = chdir("/home/anon");
  200. ASSERT(rc == 0);
  201. }
  202. int main(int, char**)
  203. {
  204. int rc;
  205. EXPECT_ERROR_2(ENOTDIR, open, "/dev/zero", (O_DIRECTORY | O_RDONLY));
  206. EXPECT_ERROR_2(EINVAL, open, "/dev/zero", (O_DIRECTORY | O_CREAT | O_RDWR));
  207. EXPECT_ERROR_2(EEXIST, open, "/dev/zero", (O_CREAT | O_EXCL | O_RDWR));
  208. EXPECT_ERROR_2(EINVAL, open, "/tmp/abcdef", (O_DIRECTORY | O_CREAT | O_RDWR));
  209. EXPECT_ERROR_2(EACCES, open, "/proc/all", (O_RDWR));
  210. EXPECT_ERROR_2(ENOENT, open, "/boof/baaf/nonexistent", (O_CREAT | O_RDWR));
  211. EXPECT_ERROR_2(EISDIR, open, "/tmp", (O_DIRECTORY | O_RDWR));
  212. test_read_from_directory();
  213. test_write_to_directory();
  214. test_read_from_writeonly();
  215. test_write_to_readonly();
  216. test_read_past_eof();
  217. test_ftruncate_readonly();
  218. test_ftruncate_negative();
  219. test_mmap_directory();
  220. test_tmpfs_read_past_end();
  221. test_procfs_read_past_end();
  222. test_open_create_device();
  223. test_unlink_symlink();
  224. test_eoverflow();
  225. test_rmdir_while_inside_dir();
  226. return 0;
  227. }