Branch :
/* ext4fs
* Copyright 2025 kmx.io <contact@kmx.io>
*
* Permission is hereby granted to use this software granted the above
* copyright notice and this permission paragraph are included in all
* copies and substantial portions of this software.
*
* THIS SOFTWARE IS PROVIDED "AS-IS" WITHOUT ANY GUARANTEE OF
* PURPOSE AND PERFORMANCE. IN NO EVENT WHATSOEVER SHALL THE
* AUTHOR BE CONSIDERED LIABLE FOR THE USE AND PERFORMANCE OF
* THIS SOFTWARE.
*/
#include <inttypes.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <strings.h>
#include <ext4fs.h>
#include <crc32c.h>
#include <uuid.h>
static int g_test_argc = 0;
static char **g_test_argv = NULL;
static long g_test_ko = 0;
static long g_test_ok = 0;
static long g_test_total = 0;
static const uint8_t g_test_bgd_data[64] = {
0x03, 0x04, 0x00, 0x00, 0x13, 0x04, 0x00, 0x00,
0x23, 0x04, 0x00, 0x00, 0x07, 0x5C, 0xC5, 0x1F,
0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
0xCB, 0x35, 0x02, 0x35, 0xC5, 0x1F, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x3B, 0x1D, 0x72, 0x80, 0x00, 0x00, 0x00, 0x00
};
static const uint8_t g_test_sb_data[1024] = {
0xe0, 0xa9, 0x0e, 0x00, 0x40, 0x93, 0x3a, 0x00,
0xc3, 0xed, 0x02, 0x00, 0x92, 0x3f, 0x39, 0x00,
0xd5, 0xa9, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00,
0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
0xd0, 0x1f, 0x00, 0x00, 0x75, 0xfb, 0x7f, 0x68,
0x03, 0x00, 0x80, 0x68, 0x11, 0x00, 0xff, 0xff,
0x53, 0xef, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00,
0xae, 0x9f, 0x61, 0x68, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
0x00, 0x01, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,
0xc2, 0x02, 0x00, 0x00, 0x6b, 0x04, 0x00, 0x00,
0x31, 0x88, 0xb7, 0x06, 0xd0, 0xcb, 0x42, 0x1f,
0xb9, 0x61, 0xd9, 0x13, 0x63, 0xe4, 0x41, 0x58,
0x65, 0x78, 0x74, 0x34, 0x66, 0x73, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x5e, 0x68, 0x93, 0x7f,
0x43, 0x87, 0x4f, 0xae, 0x93, 0x67, 0xc0, 0x02,
0x89, 0xeb, 0x8f, 0x55, 0x01, 0x01, 0x40, 0x00,
0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xae, 0x9f, 0x61, 0x68, 0x0a, 0xf3, 0x01, 0x00,
0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00,
0x03, 0x84, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x20, 0x00,
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x04, 0x01, 0x00, 0x00,
0xb9, 0xbd, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xa8, 0x53, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x9f, 0xe2, 0xac, 0xe3
};
#define TEST_ASSERT(test) \
do { \
if (! (test)) { \
fprintf(stderr, "KO: %s\n", # test); \
g_test_ko++; \
g_test_total++; \
} \
else { \
g_test_ok++; \
g_test_total++; \
} \
} while (0)
#define TEST_EQ(test, expected) \
do { \
int64_t i_test = (test); \
int64_t i_expected = (expected); \
if (! ((i_test) == (i_expected))) { \
fprintf(stderr, "KO: expected %s == %" PRId64 ", got %" PRId64 \
" instead\n", \
# test, i_expected, i_test); \
g_test_ko++; \
g_test_total++; \
} \
else { \
g_test_ok++; \
g_test_total++; \
} \
} while (0)
void test_summary (void)
{
fflush(stdout);
fprintf(stderr, "OK: %ld\tKO: %ld\tTotal: %ld\n",
g_test_ok, g_test_ko, g_test_total);
fflush(stderr);
}
void test_crc32c (void)
{
uint8_t b[32] = {0};
uint32_t u32 = 0;
TEST_EQ(crc32c(0, &u32, 4), 0x48674BC7U);
TEST_EQ(crc32c(0, b, sizeof(b)), 0x8A9136AAU);
memset(b, -1, sizeof(b));
TEST_EQ(crc32c(0, b, sizeof(b)), 0x62A8AB43U);
TEST_EQ(crc32c(0, "123456789", 9), 0xE3069283U);
TEST_EQ(crc32c(crc32c(0, "1", 1), "23456789", 8),
0xE3069283U);
TEST_EQ(crc32c(crc32c(0, "12", 2), "3456789", 7),
0xE3069283U);
TEST_EQ(crc32c(crc32c(0, "123", 3), "456789", 6),
0xE3069283U);
TEST_EQ(crc32c(crc32c(0, "1234", 4), "56789", 5),
0xE3069283U);
TEST_EQ(crc32c(crc32c(0, "12345", 5), "6789", 4),
0xE3069283U);
TEST_EQ(crc32c(crc32c(0, "123456", 6), "789", 3),
0xE3069283U);
TEST_EQ(crc32c(crc32c(0, "1234567", 7), "89", 2),
0xE3069283U);
TEST_EQ(crc32c(crc32c(0, "12345678", 8), "9", 1),
0xE3069283U);
TEST_EQ(crc32c(crc32c(crc32c(0, "123", 3), "456", 3), "789", 3),
0xE3069283U);
}
void test_bgd (void)
{
struct ext4fs_super_block sb = {0};
struct ext4fs_block_group_descriptor bgd = {0};
uint16_t bgd_checksum = 0;
TEST_EQ(offsetof(struct ext4fs_block_group_descriptor, bgd_checksum),
0x1E);
TEST_EQ(sizeof(struct ext4fs_block_group_descriptor),
64);
memcpy(&sb, g_test_sb_data, sizeof(sb));
memcpy(&bgd, g_test_bgd_data, sizeof(bgd));
TEST_EQ(ext4fs_bgd_checksum_compute(&sb, &bgd, 0, &bgd_checksum), 0);
TEST_EQ(bgd_checksum, 0x7E71U);
}
void test_inode (void)
{
TEST_EQ(offsetof(struct ext4fs_inode, i_mode), 0);
TEST_EQ(offsetof(struct ext4fs_inode, i_mtime), 0x10);
TEST_EQ(offsetof(struct ext4fs_inode, i_flags), 0x20);
TEST_EQ(offsetof(struct ext4fs_inode, i_nfs_generation), 0x64);
TEST_EQ(offsetof(struct ext4fs_inode, i_fragment_address), 0x70);
TEST_EQ(offsetof(struct ext4fs_inode, i_extra_isize), 0x80);
TEST_EQ(sizeof(struct ext4fs_inode), 0xA0);
TEST_EQ(sizeof(struct ext4fs_inode_256), 256);
}
void test_sb (void)
{
struct ext4fs_super_block sb = {0};
uint32_t sb_checksum;
TEST_EQ(offsetof(struct ext4fs_super_block, sb_default_mount_opts),
0x100);
TEST_EQ(offsetof(struct ext4fs_super_block, sb_mount_opts), 0x200);
TEST_EQ(offsetof(struct ext4fs_super_block, sb_orphan_file_inode),
0x280);
TEST_EQ(offsetof(struct ext4fs_super_block, sb_checksum), 0x3FC);
TEST_EQ(sizeof(sb.sb_uuid), 16);
TEST_EQ(sizeof(struct ext4fs_super_block), 1024);
memcpy(&sb, g_test_sb_data, sizeof(sb));
TEST_EQ(ext4fs_sb_checksum_compute(&sb, &sb_checksum), 0);
TEST_EQ(sb_checksum, 0xE3ACE29FU);
}
#define TEST_CASE_RUN(name) \
do { \
int i = 1; \
if (g_test_argc == 1) \
test_ ## name(); \
else { \
while (i < g_test_argc) { \
if (! strcmp(g_test_argv[i], # name)) { \
test_ ## name(); \
break; \
} \
i++; \
} \
} \
} while (0)
int main (int argc, char **argv)
{
g_test_argc = argc;
g_test_argv = argv;
TEST_CASE_RUN(crc32c);
TEST_CASE_RUN(sb);
TEST_CASE_RUN(bgd);
TEST_CASE_RUN(inode);
test_summary();
return g_test_ko ? 1 : 0;
}