test-fs-open-flags.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435
  1. /* Copyright libuv project contributors. All rights reserved.
  2. *
  3. * Permission is hereby granted, free of charge, to any person obtaining a copy
  4. * of this software and associated documentation files (the "Software"), to
  5. * deal in the Software without restriction, including without limitation the
  6. * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  7. * sell copies of the Software, and to permit persons to whom the Software is
  8. * furnished to do so, subject to the following conditions:
  9. *
  10. * The above copyright notice and this permission notice shall be included in
  11. * all copies or substantial portions of the Software.
  12. *
  13. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  14. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  15. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  16. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  17. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  18. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  19. * IN THE SOFTWARE.
  20. */
  21. #ifdef _WIN32
  22. #include "uv.h"
  23. #include "task.h"
  24. #if defined(__unix__) || defined(__POSIX__) || \
  25. defined(__APPLE__) || defined(__sun) || \
  26. defined(_AIX) || defined(__MVS__) || \
  27. defined(__HAIKU__)
  28. # include <unistd.h> /* unlink, rmdir */
  29. #else
  30. # include <direct.h>
  31. # define rmdir _rmdir
  32. # define unlink _unlink
  33. #endif
  34. static int flags;
  35. static uv_fs_t close_req;
  36. static uv_fs_t mkdir_req;
  37. static uv_fs_t open_req;
  38. static uv_fs_t read_req;
  39. static uv_fs_t rmdir_req;
  40. static uv_fs_t unlink_req;
  41. static uv_fs_t write_req;
  42. static char buf[32];
  43. static uv_buf_t iov;
  44. /* Opening the same file multiple times quickly can cause uv_fs_open to fail
  45. * with EBUSY, so append an identifier to the file name for each operation */
  46. static int sid = 0;
  47. #define FILE_NAME_SIZE 128
  48. static char absent_file[FILE_NAME_SIZE];
  49. static char empty_file[FILE_NAME_SIZE];
  50. static char dummy_file[FILE_NAME_SIZE];
  51. static char empty_dir[] = "empty_dir";
  52. static void setup() {
  53. int r;
  54. /* empty_dir */
  55. r = uv_fs_rmdir(NULL, &rmdir_req, empty_dir, NULL);
  56. ASSERT(r == 0 || r == UV_ENOENT);
  57. ASSERT(rmdir_req.result == 0 || rmdir_req.result == UV_ENOENT);
  58. uv_fs_req_cleanup(&rmdir_req);
  59. r = uv_fs_mkdir(NULL, &mkdir_req, empty_dir, 0755, NULL);
  60. ASSERT(r == 0);
  61. ASSERT(mkdir_req.result == 0);
  62. uv_fs_req_cleanup(&mkdir_req);
  63. }
  64. static void refresh() {
  65. int r;
  66. /* absent_file */
  67. sprintf(absent_file, "test_file_%d", sid++);
  68. r = uv_fs_unlink(NULL, &unlink_req, absent_file, NULL);
  69. ASSERT(r == 0 || r == UV_ENOENT);
  70. ASSERT(unlink_req.result == 0 || unlink_req.result == UV_ENOENT);
  71. uv_fs_req_cleanup(&unlink_req);
  72. /* empty_file */
  73. sprintf(empty_file, "test_file_%d", sid++);
  74. r = uv_fs_open(NULL, &open_req, empty_file,
  75. UV_FS_O_TRUNC | UV_FS_O_CREAT | UV_FS_O_WRONLY, S_IWUSR | S_IRUSR, NULL);
  76. ASSERT(r >= 0);
  77. ASSERT(open_req.result >= 0);
  78. uv_fs_req_cleanup(&open_req);
  79. r = uv_fs_close(NULL, &close_req, open_req.result, NULL);
  80. ASSERT(r == 0);
  81. ASSERT(close_req.result == 0);
  82. uv_fs_req_cleanup(&close_req);
  83. /* dummy_file */
  84. sprintf(dummy_file, "test_file_%d", sid++);
  85. r = uv_fs_open(NULL, &open_req, dummy_file,
  86. UV_FS_O_TRUNC | UV_FS_O_CREAT | UV_FS_O_WRONLY, S_IWUSR | S_IRUSR, NULL);
  87. ASSERT(r >= 0);
  88. ASSERT(open_req.result >= 0);
  89. uv_fs_req_cleanup(&open_req);
  90. iov = uv_buf_init("a", 1);
  91. r = uv_fs_write(NULL, &write_req, open_req.result, &iov, 1, -1, NULL);
  92. ASSERT(r == 1);
  93. ASSERT(write_req.result == 1);
  94. uv_fs_req_cleanup(&write_req);
  95. r = uv_fs_close(NULL, &close_req, open_req.result, NULL);
  96. ASSERT(r == 0);
  97. ASSERT(close_req.result == 0);
  98. uv_fs_req_cleanup(&close_req);
  99. }
  100. static void cleanup() {
  101. unlink(absent_file);
  102. unlink(empty_file);
  103. unlink(dummy_file);
  104. }
  105. static void openFail(char *file, int error) {
  106. int r;
  107. refresh();
  108. r = uv_fs_open(NULL, &open_req, file, flags, S_IWUSR | S_IRUSR, NULL);
  109. ASSERT(r == error);
  110. ASSERT(open_req.result == error);
  111. uv_fs_req_cleanup(&open_req);
  112. /* Ensure the first call does not create the file */
  113. r = uv_fs_open(NULL, &open_req, file, flags, S_IWUSR | S_IRUSR, NULL);
  114. ASSERT(r == error);
  115. ASSERT(open_req.result == error);
  116. uv_fs_req_cleanup(&open_req);
  117. cleanup();
  118. }
  119. static void refreshOpen(char *file) {
  120. int r;
  121. refresh();
  122. r = uv_fs_open(NULL, &open_req, file, flags, S_IWUSR | S_IRUSR, NULL);
  123. ASSERT(r >= 0);
  124. ASSERT(open_req.result >= 0);
  125. uv_fs_req_cleanup(&open_req);
  126. }
  127. static void writeExpect(char *file, char *expected, int size) {
  128. int r;
  129. refreshOpen(file);
  130. iov = uv_buf_init("b", 1);
  131. r = uv_fs_write(NULL, &write_req, open_req.result, &iov, 1, -1, NULL);
  132. ASSERT(r == 1);
  133. ASSERT(write_req.result == 1);
  134. uv_fs_req_cleanup(&write_req);
  135. iov = uv_buf_init("c", 1);
  136. r = uv_fs_write(NULL, &write_req, open_req.result, &iov, 1, -1, NULL);
  137. ASSERT(r == 1);
  138. ASSERT(write_req.result == 1);
  139. uv_fs_req_cleanup(&write_req);
  140. r = uv_fs_close(NULL, &close_req, open_req.result, NULL);
  141. ASSERT(r == 0);
  142. ASSERT(close_req.result == 0);
  143. uv_fs_req_cleanup(&close_req);
  144. /* Check contents */
  145. r = uv_fs_open(NULL, &open_req, file, UV_FS_O_RDONLY, S_IWUSR | S_IRUSR, NULL);
  146. ASSERT(r >= 0);
  147. ASSERT(open_req.result >= 0);
  148. uv_fs_req_cleanup(&open_req);
  149. iov = uv_buf_init(buf, sizeof(buf));
  150. r = uv_fs_read(NULL, &read_req, open_req.result, &iov, 1, -1, NULL);
  151. ASSERT(r == size);
  152. ASSERT(read_req.result == size);
  153. ASSERT(strncmp(buf, expected, size) == 0);
  154. uv_fs_req_cleanup(&read_req);
  155. r = uv_fs_close(NULL, &close_req, open_req.result, NULL);
  156. ASSERT(r == 0);
  157. ASSERT(close_req.result == 0);
  158. uv_fs_req_cleanup(&close_req);
  159. cleanup();
  160. }
  161. static void writeFail(char *file, int error) {
  162. int r;
  163. refreshOpen(file);
  164. iov = uv_buf_init("z", 1);
  165. r = uv_fs_write(NULL, &write_req, open_req.result, &iov, 1, -1, NULL);
  166. ASSERT(r == error);
  167. ASSERT(write_req.result == error);
  168. uv_fs_req_cleanup(&write_req);
  169. iov = uv_buf_init("z", 1);
  170. r = uv_fs_write(NULL, &write_req, open_req.result, &iov, 1, -1, NULL);
  171. ASSERT(r == error);
  172. ASSERT(write_req.result == error);
  173. uv_fs_req_cleanup(&write_req);
  174. r = uv_fs_close(NULL, &close_req, open_req.result, NULL);
  175. ASSERT(r == 0);
  176. ASSERT(close_req.result == 0);
  177. uv_fs_req_cleanup(&close_req);
  178. cleanup();
  179. }
  180. static void readExpect(char *file, char *expected, int size) {
  181. int r;
  182. refreshOpen(file);
  183. iov = uv_buf_init(buf, sizeof(buf));
  184. r = uv_fs_read(NULL, &read_req, open_req.result, &iov, 1, -1, NULL);
  185. ASSERT(r == size);
  186. ASSERT(read_req.result == size);
  187. ASSERT(strncmp(buf, expected, size) == 0);
  188. uv_fs_req_cleanup(&read_req);
  189. r = uv_fs_close(NULL, &close_req, open_req.result, NULL);
  190. ASSERT(r == 0);
  191. ASSERT(close_req.result == 0);
  192. uv_fs_req_cleanup(&close_req);
  193. cleanup();
  194. }
  195. static void readFail(char *file, int error) {
  196. int r;
  197. refreshOpen(file);
  198. iov = uv_buf_init(buf, sizeof(buf));
  199. r = uv_fs_read(NULL, &read_req, open_req.result, &iov, 1, -1, NULL);
  200. ASSERT(r == error);
  201. ASSERT(read_req.result == error);
  202. uv_fs_req_cleanup(&read_req);
  203. iov = uv_buf_init(buf, sizeof(buf));
  204. r = uv_fs_read(NULL, &read_req, open_req.result, &iov, 1, -1, NULL);
  205. ASSERT(r == error);
  206. ASSERT(read_req.result == error);
  207. uv_fs_req_cleanup(&read_req);
  208. r = uv_fs_close(NULL, &close_req, open_req.result, NULL);
  209. ASSERT(r == 0);
  210. ASSERT(close_req.result == 0);
  211. uv_fs_req_cleanup(&close_req);
  212. cleanup();
  213. }
  214. static void fs_open_flags(int add_flags) {
  215. /* Follow the order from
  216. * https://github.com/nodejs/node/blob/1a96abe849/lib/internal/fs/utils.js#L329-L354
  217. */
  218. /* r */
  219. flags = add_flags | UV_FS_O_RDONLY;
  220. openFail(absent_file, UV_ENOENT);
  221. writeFail(empty_file, UV_EPERM);
  222. readExpect(empty_file, "", 0);
  223. writeFail(dummy_file, UV_EPERM);
  224. readExpect(dummy_file, "a", 1);
  225. writeFail(empty_dir, UV_EPERM);
  226. readFail(empty_dir, UV_EISDIR);
  227. /* rs */
  228. flags = add_flags | UV_FS_O_RDONLY | UV_FS_O_SYNC;
  229. openFail(absent_file, UV_ENOENT);
  230. writeFail(empty_file, UV_EPERM);
  231. readExpect(empty_file, "", 0);
  232. writeFail(dummy_file, UV_EPERM);
  233. readExpect(dummy_file, "a", 1);
  234. writeFail(empty_dir, UV_EPERM);
  235. readFail(empty_dir, UV_EISDIR);
  236. /* r+ */
  237. flags = add_flags | UV_FS_O_RDWR;
  238. openFail(absent_file, UV_ENOENT);
  239. writeExpect(empty_file, "bc", 2);
  240. readExpect(empty_file, "", 0);
  241. writeExpect(dummy_file, "bc", 2);
  242. readExpect(dummy_file, "a", 1);
  243. writeFail(empty_dir, UV_EISDIR);
  244. readFail(empty_dir, UV_EISDIR);
  245. /* rs+ */
  246. flags = add_flags | UV_FS_O_RDWR | UV_FS_O_SYNC;
  247. openFail(absent_file, UV_ENOENT);
  248. writeExpect(empty_file, "bc", 2);
  249. readExpect(empty_file, "", 0);
  250. writeExpect(dummy_file, "bc", 2);
  251. readExpect(dummy_file, "a", 1);
  252. writeFail(empty_dir, UV_EISDIR);
  253. readFail(empty_dir, UV_EISDIR);
  254. /* w */
  255. flags = add_flags | UV_FS_O_TRUNC | UV_FS_O_CREAT | UV_FS_O_WRONLY;
  256. writeExpect(absent_file, "bc", 2);
  257. readFail(absent_file, UV_EPERM);
  258. writeExpect(empty_file, "bc", 2);
  259. readFail(empty_file, UV_EPERM);
  260. writeExpect(dummy_file, "bc", 2);
  261. readFail(dummy_file, UV_EPERM);
  262. openFail(empty_dir, UV_EISDIR);
  263. /* wx */
  264. flags = add_flags | UV_FS_O_TRUNC | UV_FS_O_CREAT | UV_FS_O_WRONLY |
  265. UV_FS_O_EXCL;
  266. writeExpect(absent_file, "bc", 2);
  267. readFail(absent_file, UV_EPERM);
  268. openFail(empty_file, UV_EEXIST);
  269. openFail(dummy_file, UV_EEXIST);
  270. openFail(empty_dir, UV_EEXIST);
  271. /* w+ */
  272. flags = add_flags | UV_FS_O_TRUNC | UV_FS_O_CREAT | UV_FS_O_RDWR;
  273. writeExpect(absent_file, "bc", 2);
  274. readExpect(absent_file, "", 0);
  275. writeExpect(empty_file, "bc", 2);
  276. readExpect(empty_file, "", 0);
  277. writeExpect(dummy_file, "bc", 2);
  278. readExpect(dummy_file, "", 0);
  279. openFail(empty_dir, UV_EISDIR);
  280. /* wx+ */
  281. flags = add_flags | UV_FS_O_TRUNC | UV_FS_O_CREAT | UV_FS_O_RDWR |
  282. UV_FS_O_EXCL;
  283. writeExpect(absent_file, "bc", 2);
  284. readExpect(absent_file, "", 0);
  285. openFail(empty_file, UV_EEXIST);
  286. openFail(dummy_file, UV_EEXIST);
  287. openFail(empty_dir, UV_EEXIST);
  288. /* a */
  289. flags = add_flags | UV_FS_O_APPEND | UV_FS_O_CREAT | UV_FS_O_WRONLY;
  290. writeExpect(absent_file, "bc", 2);
  291. readFail(absent_file, UV_EPERM);
  292. writeExpect(empty_file, "bc", 2);
  293. readFail(empty_file, UV_EPERM);
  294. writeExpect(dummy_file, "abc", 3);
  295. readFail(dummy_file, UV_EPERM);
  296. writeFail(empty_dir, UV_EISDIR);
  297. readFail(empty_dir, UV_EPERM);
  298. /* ax */
  299. flags = add_flags | UV_FS_O_APPEND | UV_FS_O_CREAT | UV_FS_O_WRONLY |
  300. UV_FS_O_EXCL;
  301. writeExpect(absent_file, "bc", 2);
  302. readFail(absent_file, UV_EPERM);
  303. openFail(empty_file, UV_EEXIST);
  304. openFail(dummy_file, UV_EEXIST);
  305. openFail(empty_dir, UV_EEXIST);
  306. /* as */
  307. flags = add_flags | UV_FS_O_APPEND | UV_FS_O_CREAT | UV_FS_O_WRONLY |
  308. UV_FS_O_SYNC;
  309. writeExpect(absent_file, "bc", 2);
  310. readFail(absent_file, UV_EPERM);
  311. writeExpect(empty_file, "bc", 2);
  312. readFail(empty_file, UV_EPERM);
  313. writeExpect(dummy_file, "abc", 3);
  314. readFail(dummy_file, UV_EPERM);
  315. writeFail(empty_dir, UV_EISDIR);
  316. readFail(empty_dir, UV_EPERM);
  317. /* a+ */
  318. flags = add_flags | UV_FS_O_APPEND | UV_FS_O_CREAT | UV_FS_O_RDWR;
  319. writeExpect(absent_file, "bc", 2);
  320. readExpect(absent_file, "", 0);
  321. writeExpect(empty_file, "bc", 2);
  322. readExpect(empty_file, "", 0);
  323. writeExpect(dummy_file, "abc", 3);
  324. readExpect(dummy_file, "a", 1);
  325. writeFail(empty_dir, UV_EISDIR);
  326. readFail(empty_dir, UV_EISDIR);
  327. /* ax+ */
  328. flags = add_flags | UV_FS_O_APPEND | UV_FS_O_CREAT | UV_FS_O_RDWR |
  329. UV_FS_O_EXCL;
  330. writeExpect(absent_file, "bc", 2);
  331. readExpect(absent_file, "", 0);
  332. openFail(empty_file, UV_EEXIST);
  333. openFail(dummy_file, UV_EEXIST);
  334. openFail(empty_dir, UV_EEXIST);
  335. /* as+ */
  336. flags = add_flags | UV_FS_O_APPEND | UV_FS_O_CREAT | UV_FS_O_RDWR |
  337. UV_FS_O_SYNC;
  338. writeExpect(absent_file, "bc", 2);
  339. readExpect(absent_file, "", 0);
  340. writeExpect(empty_file, "bc", 2);
  341. readExpect(empty_file, "", 0);
  342. writeExpect(dummy_file, "abc", 3);
  343. readExpect(dummy_file, "a", 1);
  344. writeFail(empty_dir, UV_EISDIR);
  345. readFail(empty_dir, UV_EISDIR);
  346. }
  347. TEST_IMPL(fs_open_flags) {
  348. setup();
  349. fs_open_flags(0);
  350. fs_open_flags(UV_FS_O_FILEMAP);
  351. /* Cleanup. */
  352. rmdir(empty_dir);
  353. MAKE_VALGRIND_HAPPY();
  354. return 0;
  355. }
  356. #else
  357. typedef int file_has_no_tests; /* ISO C forbids an empty translation unit. */
  358. #endif /* ifndef _WIN32 */