From 0e71a3bb327b96e549de7f1b8663f43dc6a7a29f Mon Sep 17 00:00:00 2001 From: Robert Pengelly Date: Sun, 31 Aug 2025 20:10:00 +0100 Subject: [PATCH] Support bigendian --- common.c | 213 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- common.h | 1 + e2cp.c | 21 ++++-- e2md.c | 19 +++-- mke2fs.c | 25 ++++--- 5 files changed, 257 insertions(+), 22 deletions(-) diff --git a/common.c b/common.c index aff66f1..560f16e 100644 --- a/common.c +++ b/common.c @@ -10,11 +10,163 @@ #include "inode.h" #include "report.h" +static void swap16 (unsigned char *arr) { + + unsigned char temp[2]; + memcpy (temp, arr, 2); + + arr[0] = temp[1]; + arr[1] = temp[0]; + +} + +static void swap32 (unsigned char *arr) { + + unsigned char temp[4]; + memcpy (temp, arr, 4); + + arr[0] = temp[3]; + arr[1] = temp[2]; + arr[2] = temp[1]; + arr[3] = temp[0]; + +} + +static void swap32_byte_array (unsigned char *arr, unsigned long n) { + + unsigned char *temp = xmalloc (n * 4); + unsigned long i; + + memcpy (temp, arr, n * 4); + + for (i = 0; i < n; i++) { + + arr[(i * 4) + 0] = temp[(i * 4) + 3]; + arr[(i * 4) + 1] = temp[(i * 4) + 2]; + arr[(i * 4) + 2] = temp[(i * 4) + 1]; + arr[(i * 4) + 3] = temp[(i * 4) + 0]; + + } + + free (temp); + +} + +static void swap_sb (struct superblock *sb) { + + swap32 (sb->s_inodes_count); + swap32 (sb->s_blocks_count); + + swap32 (sb->s_r_blocks_count); + + swap32 (sb->s_free_blocks_count); + swap32 (sb->s_free_inodes_count); + + swap32 (sb->s_first_data_block); + + swap32 (sb->s_log_block_size); + swap32 (sb->s_log_frag_size); + + swap32 (sb->s_blocks_per_group); + swap32 (sb->s_frags_per_group); + swap32 (sb->s_inodes_per_group); + + swap32 (sb->s_mtime); + swap32 (sb->s_wtime); + + swap16 (sb->s_mount_count); + swap16 (sb->s_max_mount_count); + + swap16 (sb->s_magic); + swap16 (sb->s_state); + swap16 (sb->s_errors); + + swap16 (sb->s_minor_rev_level); + + swap32 (sb->s_lastcheck); + swap32 (sb->s_checkinterval); + swap32 (sb->s_creator_os); + swap32 (sb->s_rev_level); + + swap16 (sb->s_def_resuid); + swap16 (sb->s_def_resgid); + + swap32 (sb->s_first_ino); + swap16 (sb->s_inode_size); + swap16 (sb->s_block_group_nr); + + swap32 (sb->s_feature_compat); + swap32 (sb->s_feature_incompat); + swap32 (sb->s_feature_ro_compat); + + swap32 (sb->s_algorithm_usage_bitmap); + +} + +static void swap_gd (struct group_descriptor *gd) { + + swap32 (gd->bg_block_bitmap); + swap32 (gd->bg_inode_bitmap); + swap32 (gd->bg_inode_table); + + swap16 (gd->bg_free_blocks_count); + swap16 (gd->bg_free_inodes_count); + swap16 (gd->bg_used_dirs_count); + +} + +static void swap_nod (struct inode *nod) { + + swap16 (nod->i_mode); + swap16 (nod->i_uid); + swap32 (nod->i_size); + + swap32 (nod->i_atime); + swap32 (nod->i_ctime); + swap32 (nod->i_mtime); + swap32 (nod->i_dtime); + + swap16 (nod->i_gid); + swap16 (nod->i_nlinks); + + swap32 (nod->i_blocks); + swap32 (nod->i_flags); + + swap32_byte_array (nod->i_block, EXT2_NBLOCKS); + swap32 (nod->i_version); + + swap32 (nod->i_file_acl); + swap32 (nod->i_dir_acl); + + swap32 (nod->i_faddr); + +} + +static void swap_dir (struct directory *dir) { + + swap32 (dir->d_inode); + + swap16 (dir->d_rec_len); + swap16 (dir->d_name_len); + +} + +static void swap_block (unsigned char *block) { + + unsigned long i; + + for (i = 0; i < BLOCKSIZE; i += 4) { + swap32 (block + i); + } + +} + unsigned long offset = 0; char *program_name = 0; char *outfile = 0; +int bigendian = 0; FILE *ofp = 0; int seekto (FILE *fp, unsigned long sector) { @@ -176,8 +328,12 @@ static unsigned long gd_elem_val (struct cache_link *elem) { static void gd_freed (struct cache_link *elem) { struct gd_info *gi = container_of (elem, struct gd_info, link); - put_blk (gi->bi); + if (gi->fs->swapit) { + swap_gd (gi->gd); + } + + put_blk (gi->bi); free (gi); } @@ -208,8 +364,12 @@ static unsigned long blkmap_elem_val (struct cache_link *elem) { static void blkmap_freed (struct cache_link *elem) { struct blkmap_info *bmi = container_of (elem, struct blkmap_info, link); - put_blk (bmi->bi); + if (bmi->fs->swapit) { + swap_block (bmi->b); + } + + put_blk (bmi->bi); free (bmi); } @@ -226,8 +386,12 @@ static unsigned long inode_elem_val (struct cache_link *elem) { static void inode_freed (struct cache_link *elem) { struct nod_info *ni = container_of (elem, struct nod_info, link); - put_blk (ni->bi); + if (ni->fs->swapit) { + swap_nod (ni->itab); + } + + put_blk (ni->bi); free (ni); } @@ -262,6 +426,10 @@ struct group_descriptor *get_gd (struct filesystem *fs, unsigned long no, struct gi->gd = ((struct group_descriptor *) get_blk (fs, gdblk, &gi->bi)) + offset; cache_add (&fs->gds, &gi->link); + + if (fs->swapit) { + swap_gd (gi->gd); + } out: @@ -340,6 +508,10 @@ void finish_fs (struct filesystem *fs) { } + if (fs->swapit) { + swap_sb (fs->sb); + } + if (seekto (ofp, EXT2_SUPERBLOCK_OFFSET / BLOCKSIZE)) { report_at (program_name, 0, REPORT_ERROR, "fseek"); @@ -353,6 +525,10 @@ void finish_fs (struct filesystem *fs) { exit (EXIT_FAILURE); } + + if (fs->swapit) { + swap_sb (fs->sb); + } } @@ -421,6 +597,10 @@ struct inode *get_nod (struct filesystem *fs, unsigned long nod, struct nod_info ni->b = get_blk (fs, byte_array_to_integer (gd->bg_inode_table, 4) + boffset, &ni->bi); ni->itab = ((struct inode *) ni->b) + offset; + if (fs->swapit) { + swap_nod (ni->itab); + } + put_gd (gi); out: @@ -764,6 +944,10 @@ static unsigned int *get_blkmap (struct filesystem *fs, unsigned long blk, struc bmi->b = get_blk (fs, blk, &bmi->bi); cache_add (&fs->blkmaps, &bmi->link); + if (fs->swapit) { + swap_block (bmi->b); + } + out: *rbmi = bmi; @@ -1291,6 +1475,10 @@ void put_dir (struct dirwalker *dw) { if (dw->need_flush) { /* Walk ended before reaching the end of block b. */ + if (dw->fs->swapit) { + swap_dir (&dw->d); + } + memcpy (dw->last_d, &dw->d, sizeof (dw->d)); } @@ -1312,6 +1500,11 @@ struct directory *get_dir (struct filesystem *fs, unsigned long nod, struct dirw dw->need_flush = 1; memcpy (&dw->d, dw->last_d, sizeof (struct directory)); + + if (fs->swapit) { + swap_dir (&dw->d); + } + return &dw->d; } @@ -1321,7 +1514,13 @@ struct directory *next_dir (struct dirwalker *dw) { unsigned char *next_d = dw->last_d + byte_array_to_integer (dw->d.d_rec_len, 2); if (dw->need_flush) { + + if (dw->fs->swapit) { + swap_dir (&dw->d); + } + memcpy (dw->last_d, &dw->d, sizeof (struct directory)); + } if (next_d - dw->b >= BLOCKSIZE) { @@ -1334,6 +1533,10 @@ struct directory *next_dir (struct dirwalker *dw) { dw->last_d = next_d; memcpy (&dw->d, next_d, sizeof (struct directory)); + if (dw->fs->swapit) { + swap_dir (&dw->d); + } + return &dw->d; } @@ -1394,6 +1597,10 @@ struct directory *shrink_dir (struct dirwalker *dw, unsigned long nod, const cha preclen = byte_array_to_integer (d->d_rec_len, 2); reclen -= preclen; + if (dw->fs->swapit) { + swap_dir (&dw->d); + } + memcpy (dw->last_d, &dw->d, sizeof (dw->d)); dw->last_d = dw->last_d + preclen; diff --git a/common.h b/common.h index e07fbca..d39c2ff 100644 --- a/common.h +++ b/common.h @@ -15,6 +15,7 @@ extern unsigned long offset; extern char *outfile; extern char *program_name; +extern int bigendian; extern FILE *ofp; int seekto (FILE *fp, unsigned long sector); diff --git a/e2cp.c b/e2cp.c index 28caf18..a2abcf7 100644 --- a/e2cp.c +++ b/e2cp.c @@ -17,11 +17,12 @@ static char *mode = 0; static char *root = 0; -#define OPTION_INPUT 0x0001 -#define OPTION_HELP 0x0002 -#define OPTION_MODE 0x0003 -#define OPTION_OFFSET 0x0004 -#define OPTION_ROOT 0x0005 +#define OPTION_BIGENDIAN 0x0001 +#define OPTION_INPUT 0x0002 +#define OPTION_HELP 0x0003 +#define OPTION_MODE 0x0004 +#define OPTION_OFFSET 0x0005 +#define OPTION_ROOT 0x0006 struct option { @@ -37,6 +38,7 @@ static struct option opts[] = { { "-i", OPTION_INPUT, OPTION_HAS_ARG }, + { "--bigendian", OPTION_BIGENDIAN, OPTION_NO_ARG }, { "--help", OPTION_HELP, OPTION_NO_ARG }, { "--mode", OPTION_MODE, OPTION_HAS_ARG }, { "--offset", OPTION_OFFSET, OPTION_HAS_ARG }, @@ -181,6 +183,13 @@ static void parse_args (int argc, char **argv, int optind) { switch (popt->index) { + case OPTION_BIGENDIAN: { + + bigendian = 1; + break; + + } + case OPTION_HELP: { print_help (); @@ -796,7 +805,7 @@ int main (int argc, char **argv) { } fs = alloc_fs (); - fs->swapit = 0; + fs->swapit = bigendian; fs->sb = ⊃ diff --git a/e2md.c b/e2md.c index f24935a..763567b 100644 --- a/e2md.c +++ b/e2md.c @@ -16,10 +16,11 @@ static char *mode = 0; -#define OPTION_INPUT 0x0001 -#define OPTION_HELP 0x0002 -#define OPTION_MODE 0x0003 -#define OPTION_OFFSET 0x0004 +#define OPTION_BIGENDIAN 0x0001 +#define OPTION_INPUT 0x0002 +#define OPTION_HELP 0x0003 +#define OPTION_MODE 0x0004 +#define OPTION_OFFSET 0x0005 struct option { @@ -35,6 +36,7 @@ static struct option opts[] = { { "-i", OPTION_INPUT, OPTION_HAS_ARG }, + { "--bigendian", OPTION_BIGENDIAN, OPTION_NO_ARG }, { "--help", OPTION_HELP, OPTION_NO_ARG }, { "--mode", OPTION_MODE, OPTION_HAS_ARG }, { "--offset", OPTION_OFFSET, OPTION_HAS_ARG }, @@ -178,6 +180,13 @@ static void parse_args (int argc, char **argv, int optind) { switch (popt->index) { + case OPTION_BIGENDIAN: { + + bigendian = 1; + break; + + } + case OPTION_HELP: { print_help (); @@ -395,7 +404,7 @@ int main (int argc, char **argv) { } fs = alloc_fs (); - fs->swapit = 0; + fs->swapit = bigendian; fs->sb = ⊃ diff --git a/mke2fs.c b/mke2fs.c index 435904e..03772d7 100644 --- a/mke2fs.c +++ b/mke2fs.c @@ -17,11 +17,12 @@ static unsigned long sectors = 0; static char *boot_sector = 0; -#define OPTION_BOOT 0x0001 -#define OPTION_HELP 0x0002 -#define OPTION_OFFSET 0x0003 -#define OPTION_SECTORS 0x0004 -#define OPTION_VERBOSE 0x0005 +#define OPTION_BIGENDIAN 0x0001 +#define OPTION_BOOT 0x0002 +#define OPTION_HELP 0x0003 +#define OPTION_OFFSET 0x0004 +#define OPTION_SECTORS 0x0005 +#define OPTION_VERBOSE 0x0006 struct option { @@ -35,6 +36,7 @@ struct option { static struct option opts[] = { + { "--bigendian", OPTION_BIGENDIAN, OPTION_NO_ARG }, { "--boot", OPTION_BOOT, OPTION_HAS_ARG }, { "--help", OPTION_HELP, OPTION_NO_ARG }, { "--offset", OPTION_OFFSET, OPTION_HAS_ARG }, @@ -153,6 +155,13 @@ static void parse_args (int argc, char **argv, int optind) { switch (popt->index) { + case OPTION_BIGENDIAN: { + + bigendian = 1; + break; + + } + case OPTION_BOOT: { if (boot_sector) { free (boot_sector); } @@ -383,7 +392,7 @@ static void uuid_generate (unsigned char out[16]) { } -static struct filesystem *init_fs (long nbblocks, long nbinodes, long nbresrvd, int holes, unsigned long fs_timestamp, unsigned long creator_os, int swapit) { +static struct filesystem *init_fs (long nbblocks, long nbinodes, long nbresrvd, int holes, unsigned long fs_timestamp, unsigned long creator_os) { struct group_descriptor *gd; struct gd_info *gi; @@ -449,7 +458,7 @@ static struct filesystem *init_fs (long nbblocks, long nbinodes, long nbresrvd, free_blocks_per_group = nbblocks_per_group - overhead_per_group; fs = alloc_fs (); - fs->swapit = swapit; + fs->swapit = bigendian; fs->sb = xmalloc (sizeof (*fs->sb)); @@ -766,7 +775,7 @@ int main (int argc, char **argv) { } - fs = init_fs (nbblocks, nbinodes, nbresrvd, holes, time (0), 0, 0); + fs = init_fs (nbblocks, nbinodes, nbresrvd, holes, time (0), 0); fs_upgrade_rev1_largefile (fs); finish_fs (fs); -- 2.34.1