/* * Copyright (c) 2023, Tim Ledbetter * * SPDX-License-Identifier: BSD-2-Clause */ #include #include #include #include #include #include TEST_CASE(test_uid_and_gid_high_bits_are_set) { static constexpr auto TEST_FILE_PATH = "/home/anon/.ext2_test"; auto uid = geteuid(); EXPECT_EQ(uid, 0u); auto fd = open(TEST_FILE_PATH, O_CREAT); VERIFY(fd != -1); auto cleanup_guard = ScopeGuard([&] { close(fd); unlink(TEST_FILE_PATH); }); EXPECT_EQ(setuid(0), 0); EXPECT_EQ(fchown(fd, 65536, 65536), 0); struct stat st; EXPECT_EQ(fstat(fd, &st), 0); EXPECT_EQ(st.st_uid, 65536u); EXPECT_EQ(st.st_gid, 65536u); } TEST_CASE(test_ext2_writes_and_reads_to_block_ranges) { static constexpr auto TEST_FILE_PATH = "/home/anon/.ext2_test"; auto fd = open(TEST_FILE_PATH, O_RDWR | O_CREAT); VERIFY(fd != -1); auto cleanup_guard = ScopeGuard([&] { close(fd); unlink(TEST_FILE_PATH); }); struct statvfs stvfs; int rc = fstatvfs(fd, &stvfs); VERIFY(rc != -1); size_t block_size = (size_t)stvfs.f_bsize; size_t ptrs_per_indirect_block = block_size / sizeof(u32); size_t direct_block_count = 12; size_t singly_indirect_block_count = ptrs_per_indirect_block; size_t doubly_indirect_block_count = pow(ptrs_per_indirect_block, 2); size_t triply_indirect_block_count = pow(ptrs_per_indirect_block, 3); size_t direct_blocks_capacity = direct_block_count; size_t singly_indirect_blocks_capacity = direct_blocks_capacity + singly_indirect_block_count; size_t doubly_indirect_blocks_capacity = singly_indirect_blocks_capacity + doubly_indirect_block_count; size_t triply_indirect_blocks_capacity = doubly_indirect_blocks_capacity + triply_indirect_block_count; char* block_buf = (char*)malloc(block_size); block_buf[0] = '!'; block_buf[block_size - 1] = '!'; char* read_buf = (char*)malloc(block_size); auto malloc_cleanup_guard = ScopeGuard([&] { free(block_buf); free(read_buf); }); auto write_then_read_block = [&](size_t block) { size_t offset = block * block_size; // write the block, and verify that write() was successful off_t seek_rc = lseek(fd, offset, SEEK_SET); VERIFY(seek_rc != -1); int nwrite = write(fd, block_buf, block_size); EXPECT((size_t)nwrite == block_size); // read the block we just wrote, and verify that read() was successful seek_rc = lseek(fd, offset, SEEK_SET); VERIFY(seek_rc != -1); int nread = read(fd, read_buf, block_size); EXPECT((size_t)nread == block_size); // verify that the block we read back is identical to the block we wrote EXPECT(memcmp(read_buf, block_buf, block_size) == 0); }; // run test on the first & last direct blocks write_then_read_block(0); write_then_read_block(direct_blocks_capacity - 1); // run test on the first & last singly indirect blocks write_then_read_block(direct_blocks_capacity); write_then_read_block(singly_indirect_blocks_capacity - 1); // run test on the first & last doubly indirect blocks write_then_read_block(singly_indirect_blocks_capacity); write_then_read_block(doubly_indirect_blocks_capacity - 1); // run test on the first & last triply indirect blocks write_then_read_block(doubly_indirect_blocks_capacity); write_then_read_block(triply_indirect_blocks_capacity - 1); }