1 // Copyright 2016 The Fuchsia Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include <errno.h>
6 
7 #include <fbl/algorithm.h>
8 
9 #include "util.h"
10 
11 #define MB (1 << 20)
12 #define PRINT_SIZE (MB * 100)
13 
test_maxfile(void)14 bool test_maxfile(void) {
15     BEGIN_TEST;
16 
17     int fd = emu_open("::bigfile", O_CREAT | O_RDWR, 0644);
18     ASSERT_GT(fd, 0);
19     char data_a[8192];
20     char data_b[8192];
21     char data_c[8192];
22     memset(data_a, 0xaa, sizeof(data_a));
23     memset(data_b, 0xbb, sizeof(data_b));
24     memset(data_c, 0xcc, sizeof(data_c));
25     ssize_t sz = 0;
26     ssize_t r;
27 
28     auto rotate = [&](const char* data) {
29         if (data == data_a) {
30             return data_b;
31         } else if (data == data_b) {
32             return data_c;
33         } else {
34             return data_a;
35         }
36     };
37 
38     const char* data = data_a;
39     for (;;) {
40         if ((r = emu_write(fd, data, sizeof(data_a))) < 0) {
41             fprintf(stderr, "bigfile received error: %s\n", strerror(errno));
42             if ((errno == EFBIG) || (errno == ENOSPC)) {
43                 // Either the file should be too big (EFBIG) or the file should
44                 // consume the whole volume (ENOSPC).
45                 fprintf(stderr, "(This was an expected error)\n");
46                 r = 0;
47             }
48             break;
49         }
50         if ((sz + r) % PRINT_SIZE < (sz % PRINT_SIZE)) {
51             fprintf(stderr, "wrote %zu MB\n", static_cast<size_t>((sz + r) / MB));
52         }
53         sz += r;
54         if (r < (ssize_t)(sizeof(data_a))) {
55             fprintf(stderr, "bigfile write short write of %ld bytes\n", r);
56             break;
57         }
58 
59         // Rotate which data buffer we use
60         data = rotate(data);
61     }
62     ASSERT_EQ(r, 0, "Saw an unexpected error from write");
63 
64     struct stat buf;
65     ASSERT_EQ(emu_fstat(fd, &buf), 0, "Couldn't stat max file");
66     ASSERT_EQ(buf.st_size, sz, "Unexpected max file size");
67 
68     // Try closing, re-opening, and verifying the file
69     ASSERT_EQ(emu_close(fd), 0);
70     fd = emu_open("::bigfile", O_RDWR, 0644);
71     char readbuf[8192];
72     ssize_t bytes_read = 0;
73     data = data_a;
74     while (bytes_read < sz) {
75         r = emu_read(fd, readbuf, sizeof(readbuf));
76         ASSERT_EQ(r, fbl::min(sz - bytes_read, static_cast<ssize_t>(sizeof(readbuf))));
77         ASSERT_EQ(memcmp(readbuf, data, r), 0, "File failed to verify");
78         data = rotate(data);
79         bytes_read += r;
80     }
81 
82     ASSERT_EQ(bytes_read, sz);
83 
84     ASSERT_EQ(emu_close(fd), 0);
85     ASSERT_EQ(run_fsck(), 0);
86     END_TEST;
87 }
88 
89 RUN_MINFS_TESTS(maxfile_tests,
90     RUN_TEST_LARGE(test_maxfile)
91 )
92