From fbaec83bc0fda4341862cc60ac9796277235e4b9 Mon Sep 17 00:00:00 2001 From: Signed-off-by: Roy Peled Date: Wed, 4 Feb 2009 14:56:54 +0100 Subject: mkfs.cramfs: add endianness support to cramfs tools cramfs is an endianness dependent file system. So far, the cramfs utilities did not support cramfs images of different endianness than the host machine. A separate utility, cramfsswap, was required in order to change the endianness of the image before and after using cramfs utilities. The extra utility introduced extra maintenance and an additional step in the process. This patch adds endianness support to mkfs.cramfs and fsck.cramfs. fsck.cramfs now automatically detects the image endianness, and can work on images of either endianness. mkfs.cramfs now accepts a new optional parameter (-N) that allows creating the cramfs image in either endianness. Signed-off-by: Roy Peled Signed-off-by: Karel Zak --- disk-utils/cramfs_common.c | 105 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 disk-utils/cramfs_common.c (limited to 'disk-utils/cramfs_common.c') diff --git a/disk-utils/cramfs_common.c b/disk-utils/cramfs_common.c new file mode 100644 index 000000000..ffdad9b09 --- /dev/null +++ b/disk-utils/cramfs_common.c @@ -0,0 +1,105 @@ +/* + * cramfs_common - cramfs common code + * + * Copyright (c) 2008 Roy Peled, the.roy.peled -at- gmail.com + * Copyright (c) 2004-2006 by Michael Holzt, kju -at- fqdn.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include +#include "cramfs_common.h" +#include "../include/bitops.h" + +u32 u32_toggle_endianness(int big_endian, u32 what) +{ + return big_endian == HOST_IS_BIG_ENDIAN ? what : swab32(what); +} + +void super_toggle_endianness(int big_endian, struct cramfs_super *super) +{ + if (big_endian != HOST_IS_BIG_ENDIAN) { + super->magic = swab32(super->magic); + super->size = swab32(super->size); + super->flags = swab32(super->flags); + super->future = swab32(super->future); + super->fsid.crc = swab32(super->fsid.crc); + super->fsid.edition = swab32(super->fsid.edition); + super->fsid.blocks = swab32(super->fsid.blocks); + super->fsid.files = swab32(super->fsid.files); + } +} + +void inode_toggle_endianness(int input_big_endian, int output_big_endian, struct cramfs_inode *inode_in, struct cramfs_inode *inode_out) +{ + if (input_big_endian == output_big_endian) { + memmove(inode_out, inode_in, sizeof(*inode_out)); + } + else { + unsigned char inode_out_buf[sizeof(*inode_in)]; + unsigned char *inode_in_buf = (unsigned char*)inode_in; + + inode_out_buf[0] = inode_in_buf[1]; /* 16 bit: mode */ + inode_out_buf[1] = inode_in_buf[0]; + + inode_out_buf[2] = inode_in_buf[3]; /* 16 bit: uid */ + inode_out_buf[3] = inode_in_buf[2]; + + inode_out_buf[4] = inode_in_buf[6]; /* 24 bit: size */ + inode_out_buf[5] = inode_in_buf[5]; + inode_out_buf[6] = inode_in_buf[4]; + + inode_out_buf[7] = inode_in_buf[7]; /* 8 bit: gid width */ + + /* Stop the madness! Outlaw C bitfields! They are unportable and nasty! + See for yourself what a mess this is: */ + + if (output_big_endian) { + inode_out_buf[ 8] = ( (inode_in_buf[ 8]&0x3F) << 2 ) | + ( (inode_in_buf[11]&0xC0) >> 6 ); + + inode_out_buf[ 9] = ( (inode_in_buf[11]&0x3F) << 2 ) | + ( (inode_in_buf[10]&0xC0) >> 6 ); + + inode_out_buf[10] = ( (inode_in_buf[10]&0x3F) << 2 ) | + ( (inode_in_buf[ 9]&0xC0) >> 6 ); + + inode_out_buf[11] = ( (inode_in_buf[ 9]&0x3F) << 2 ) | + ( (inode_in_buf[ 8]&0xC0) >> 6 ); + } + else { + inode_out_buf[ 8] = ( (inode_in_buf[ 8]&0xFD) >> 2 ) | + ( (inode_in_buf[11]&0x03) << 6 ); + + inode_out_buf[ 9] = ( (inode_in_buf[11]&0xFD) >> 2 ) | + ( (inode_in_buf[10]&0x03) << 6 ); + + inode_out_buf[10] = ( (inode_in_buf[10]&0xFD) >> 2 ) | + ( (inode_in_buf[ 9]&0x03) << 6 ); + + inode_out_buf[11] = ( (inode_in_buf[ 9]&0xFD) >> 2 ) | + ( (inode_in_buf[ 8]&0x03) << 6 ); + } + + memmove(inode_out, inode_out_buf, sizeof(*inode_out)); + } +} + +void inode_to_host(int from_big_endian, struct cramfs_inode *inode_in, struct cramfs_inode *inode_out) +{ + inode_toggle_endianness(from_big_endian, HOST_IS_BIG_ENDIAN, inode_in, inode_out); +} + +void inode_from_host(int to_big_endian, struct cramfs_inode *inode_in, struct cramfs_inode *inode_out) +{ + inode_toggle_endianness(HOST_IS_BIG_ENDIAN, to_big_endian, inode_in, inode_out); +} -- cgit v1.2.3-55-g7522