/test/test58.c

http://www.minix3.org/ · C · 181 lines · 110 code · 24 blank · 47 comment · 62 complexity · a4e234a741da4a29a2cbed81a714191e MD5 · raw file

  1. /* This tests the behavior of Minix when the current working dir (cwd) doesn't
  2. * actually exist and we either:
  3. * - create a new file
  4. * - make a new directory
  5. * - make a special file (mknod)
  6. * - create a hard link
  7. * - create a symbolic link, or
  8. * - rename a file
  9. * In each case, `a component of the path does not name an existing file', and
  10. * the operation should fail with ENOENT. These tests should actually be
  11. * distributed over the other tests that actually test the specific system
  12. * calls.
  13. */
  14. #include <stdio.h>
  15. #include <errno.h>
  16. #include <fcntl.h>
  17. #include <unistd.h>
  18. #include <sys/socket.h>
  19. #include <sys/types.h>
  20. #include <sys/wait.h>
  21. #include <sys/stat.h>
  22. int subtest = -1;
  23. #define MAX_ERROR 999 /* Effectively no limit. This is necessary as this
  24. * test tries to undo errors and should therefore not
  25. * preemptively exit, as that would leave the FS
  26. * in a corrupted state. */
  27. #include "common.c"
  28. #define TEST_PATH "a/b/c"
  29. #define INTEGR_MSG "You might want to check fs integrity\n"
  30. void do_test(void);
  31. void do_test(void)
  32. {
  33. int r, fd;
  34. int s[2];
  35. char buf[1], testroot[PATH_MAX+1], renamebuf[PATH_MAX+1];
  36. subtest = 1;
  37. if (socketpair(PF_UNIX, SOCK_STREAM, 0, s) == -1) e(1);
  38. if (system("mkdir -p " TEST_PATH) == -1) e(2);
  39. if (realpath(".", testroot) == NULL) e(3);
  40. r = fork();
  41. if (r == -1) e(4);
  42. else if (r == 0) { /* Child */
  43. /* Change child's cwd to TEST_PATH */
  44. if (chdir(TEST_PATH) == -1) e(5);
  45. /* Signal parent we're ready for the test */
  46. buf[0] = 'a';
  47. if (write(s[0], buf, sizeof(buf)) != sizeof(buf)) e(6);
  48. /* Wait for parent to remove my cwd */
  49. if (read(s[0], buf, sizeof(buf)) != sizeof(buf)) e(7);
  50. /* Try to create a file */
  51. if ((fd = open("testfile", O_RDWR | O_CREAT)) != -1) {
  52. e(8);
  53. /* Uh oh. We created a file?! Try to remove it. */
  54. (void) close(fd);
  55. if (unlink("testfile") != 0) {
  56. /* This is not good. We created a file, but we can
  57. * never access it; we have a spurious inode.
  58. */
  59. e(9);
  60. printf(INTEGR_MSG);
  61. exit(errct);
  62. }
  63. }
  64. if (errno != ENOENT) e(10);
  65. /* Try to create a dir */
  66. errno = 0;
  67. if (mkdir("testdir", 0777) == 0) {
  68. e(11);
  69. /* Uh oh. This shouldn't have been possible. Try to undo. */
  70. if (rmdir("testdir") != 0) {
  71. /* Not good. */
  72. e(12);
  73. printf(INTEGR_MSG);
  74. exit(errct);
  75. }
  76. }
  77. if (errno != ENOENT) e(13);
  78. /* Try to create a special file */
  79. errno = 0;
  80. if (mknod("testnode", 0777 | S_IFIFO, 0) == 0) {
  81. e(14);
  82. /* Impossible. Try to make it unhappen. */
  83. if (unlink("testnode") != 0) {
  84. /* Not good. */
  85. e(15);
  86. printf(INTEGR_MSG);
  87. exit(errct);
  88. }
  89. }
  90. if (errno != ENOENT) e(16);
  91. /* Try to rename a file */
  92. errno = 0;
  93. /* First create a file in the test dir */
  94. snprintf(renamebuf, PATH_MAX, "%s/oldname", testroot);
  95. if ((fd = open(renamebuf, O_RDWR | O_CREAT)) == -1) e(17);
  96. if (close(fd) != 0) e(18);
  97. /* Now try to rename that file to an entry in the current, non-existing
  98. * working directory.
  99. */
  100. if (rename(renamebuf, "testrename") == 0) {
  101. e(19);
  102. /* This shouldn't have been possible. Revert the name change.
  103. */
  104. if (rename("testrename", renamebuf) != 0) {
  105. /* Failed */
  106. e(20);
  107. printf(INTEGR_MSG);
  108. exit(errct);
  109. }
  110. }
  111. /* Try to create a hard link to that file */
  112. errno = 0;
  113. if (link(renamebuf, "testhlink") == 0) {
  114. e(21);
  115. /* Try to undo the hard link to prevent fs corruption. */
  116. if (unlink("testhlink") != 0) {
  117. /* Failed. */
  118. e(22);
  119. printf(INTEGR_MSG);
  120. exit(errct);
  121. }
  122. }
  123. if (errno != ENOENT) e(23);
  124. /* Try to create a symlink */
  125. errno = 0;
  126. if (symlink(testroot, "testslink") == 0) {
  127. e(24);
  128. /* Try to remove the symlink to prevent fs corruption. */
  129. if (unlink("testslink") != 0) {
  130. /* Failed. */
  131. e(25);
  132. printf(INTEGR_MSG);
  133. exit(errct);
  134. }
  135. }
  136. if (errno != ENOENT) e(26);
  137. exit(errct);
  138. } else { /* Parent */
  139. int status;
  140. /* Wait for the child to enter the TEST_PATH dir */
  141. if (read(s[1], buf, sizeof(buf)) != sizeof(buf)) e(27);
  142. /* Delete TEST_PATH */
  143. if (rmdir(TEST_PATH) != 0) e(28);
  144. /* Tell child we removed its cwd */
  145. buf[0] = 'b';
  146. if (write(s[1], buf, sizeof(buf)) != sizeof(buf)) e(29);
  147. wait(&status);
  148. errct += WEXITSTATUS(status); /* Count errors */
  149. }
  150. }
  151. int main(int argc, char* argv[])
  152. {
  153. start(58);
  154. do_test();
  155. quit();
  156. return(-1); /* Unreachable */
  157. }