#!/bin/sh

# This script is designed to create an ext3ci module based on the ext3
# module which is case-insensitive. Fortunately, the ext3 filesystem designer
# made this extremely easy -- just change the very first function in namei.c.
# The hard part is making a copy of the module so that you can select which
# filesystems to mount case-insensitive and which to mount normally. The nice
# part about using the seperate-module approach is that there is no
# performance penalty for normal filesystems.

# INSTRUCTIONS: 
# in the linux subtree, add a directory called fs/ext3ci. Copy the two
# files (ext3ci-sed-2.6.data.1 and ext3ci-sed-2.6.sh) into that directory
# and run ext3ci-sed-2.6.sh
# Reconfigure the kernel, adding ext3ci. Rebuild. Now, mount the desired ext3
# filesystem as type "ext3ci".

# Some notes:
# 1) This module has only been tested when compiled in to the kernel with
#    the same options as ext3 which is also compiled in to the kernel.
#    It ought to work as a module, but has not been tested that way.
# 2) The quota utilities don't understand that ext3ci can have quotas.
#    You must recompile them after adding ext3ci to the list.
# 3) Create the filesystem the same way as normal: mke2fs -j /dev/hda1
#    You can also mount a previous ext3 filesystem as ext3ci and it'll work
#    fine. If you have a name collision (e.g. README and readme) both files
#    will continue to exist but only one will be accessible until the first
#    is removed or renamed.
# 4) Because the filesystem structure is identical to ext3 in every respect,
#    mount will autodetect it as ext3. You must explicity pass "-t ext3ci"
#    or define it as type ext3ci in /etc/fstab.
# 5) Little has been done to internationalize this so that it works for 
#    non-English locales, but it can be trivially made to work. Edit
#    ext3ci-sed-2.6.data.1 and change the ext3ci_lowercasemap string.
#    ext3ci_lowercasemap is used to fold the characters to their case
#    insensitive values; it should contain exactly 256 characters.
# 6) If you want utilities like "ls" to treat the files as case-insensitive,
#    try setting your locale to en_US instead of C. Use:
#    export LANG=en_US
#    export LC_TYPE=en_US
# 7) Note that many unix utilities expect files to be case sensitive. Even
#    though the filesystem itself is case-insensitive, these utilities will
#    not see it. For example, "cat read*" will not see a file named "README"
#    because the bash shell (which expands read*) will not consider README
#    to be a match. "cat readme" will dump the contents of README just fine.
#    This remains true even if you set the locale to en_US.
# 8) Yes, I know I didn't follow the kernel style conventions. Feel free to
#    use indent.
# 9) The change to the hash indexing process has not been re-evaluated since
#    dir_index was introduced to the ext3 filesystem. Expected behavior:
#    upper-case files added when fs mounted ext3 not findable when remounted
#    ext3ci. Actual behavior: not tested. 

cp ../ext3/*.c .
cp ../ext3/*.h .
cp ../../include/linux/ext3*.h .
cp ../ext3/Makefile .
if [ -f ../ext3/Kconfig ] ;then
  cp ../ext3/Kconfig .
fi
rm *.o 2>>/dev/null
rm -f ../filesystems.a

H=`ls ext3*.h | grep -v ext3ci`
for i in $H ;do
  mv $i ext3ci${i##ext3}
done
mv ext3_jbd.c ext3ci_jbd.c

for i in *.c *.h Makefile ;do
  sed '
	s/ext3/ext3ci/g
	s/EXT3/EXT3CI/g
	s/<linux\/ext3ci_fs.h>/"ext3ci_fs.h"/g
	s/<linux\/ext3ci_jbd.h>/"ext3ci_jbd.h"/g
	s/<linux\/ext3ci_fs_i.h>/"ext3ci_fs_i.h"/g
	s/<linux\/ext3ci_fs_sb.h>/"ext3ci_fs_sb.h"/g
	s/EXT3CI_SUPER_MAGIC/EXT3_SUPER_MAGIC/g
	#s/CONFIG_EXT3_FS/CONFIG_EXT3CI_FS/g
	#s/_LINUX_EXT3_/_LINUX_EXT3CI_/g
	#s/ext3ci_group_desc/ext3_group_desc/g
	#s/ext3ci_super_block/ext3_super_block/g
	# s/ext3ci_debug/ext3_debug/g
	# s/ext3ci_dir_entry/ext3_dir_entry/g
	# s/ext3ci_sb/ext3_sb/g
	# s/ext3ci_i\./ext3_i\./g
	#s/ext3ci_fs_i\./ext3_fs_i\./g
	#s/ext3ci_fs_sb\./ext3_fs_sb\./g
	# for ext3ci_fs.h
	# s/u\.ext3ci_i/u.ext3_i/g
	# s/ext3ci_inode/ext3_inode/g
	# s/ext3ci_reserve_window/ext3_reserve_window/g
	# s/ext3ci_test_bit/ext3_test_bit/g
	# s/ext3ci_clear_bit/ext3_clear_bit/g
	# s/ext3ci_set_bit/ext3_set_bit/g
	# s/ext3ci_find_next_zero_bit/ext3_find_next_zero_bit/g
	# s/ext3ci_find_first_zero_bit/ext3_find_first_zero_bit/g
	# s/EXT3CI/EXT3/g
	' ${i} > ${i}.2
  mv ${i}.2 ${i}
  echo ${i}
done

echo "Lowercase namei.c..."
LINE=`cat -n namei.c | grep memcmp | awk '{ print $1 }'`
BEFORE=`expr ${LINE} - 1`
AFTER=`expr ${LINE} + 1`
DATA=`tail -n +${LINE} namei.c | head -1`

head -${BEFORE} namei.c > namei.c.2
echo "/* ${DATA} */" >> namei.c.2
cat << EOM >> namei.c.2
  na = (unsigned char*) name;
  nb = (unsigned char*) de->name;
  for (; len>0; na++,nb++,len--)
    if (ext3ci_lowercasemap[(int) *na] != ext3ci_lowercasemap[(int) *nb])
	return 0;
  return 1;
EOM
tail -n +${AFTER} namei.c >> namei.c.2

LINE=`cat -n namei.c.2 | grep 'static.*int ext3ci_match' | awk '{ print $1 }'`
INSERTAT=`expr ${LINE} + 2`
AFTER=`expr ${LINE} + 3`

head -${INSERTAT} namei.c.2 > namei.c
echo "	unsigned char *na, *nb;" >> namei.c
tail -n +${AFTER} namei.c.2 >> namei.c

LINE=`cat -n namei.c | grep 'static.*int ext3ci_match' | awk '{ print $1 }'`
INSERTAT=`expr ${LINE} - 1`
AFTER=`expr ${LINE} + 0`

head -${INSERTAT} namei.c > namei.c.2
echo "extern const char *ext3ci_lowercasemap;" >> namei.c.2
tail -n +${AFTER} namei.c >> namei.c.2

mv namei.c.2 namei.c


echo "Lowercase namei.c"

LINE=`cat -n namei.c | grep 'static struct dentry .ext3ci_lookup' | awk '{ print $1 }'`
INSERTAT=`expr ${LINE} - 1`
AFTER=`expr ${LINE} + 0`

#echo "LINE=$LINE"
#echo "INSERTAT=$INSERTAT"
#echo "AFTER=$AFTER"

head -${INSERTAT} namei.c > namei.c.2
cat ext3ci-sed-2.6.data.1 >> namei.c.2
tail -n +${AFTER} namei.c >> namei.c.2

# bh = ext3_find_entry(dentry, &de);
LINE=`cat -n namei.c.2 | grep 'bh = ext3ci_find_entry(dentry, &de);' | \
	 awk '{ print $1 }'`
if [ "$LINE" = "" ] ;then
  # changes after 2.6.27
  LINE=`cat -n namei.c.2 | \
	grep 'bh = ext3ci_find_entry(dir, &dentry->d_name, &de);' | \
	awk '{ print $1 }'`
fi
for L in ${LINE} ;do
  INSERTAT=`expr ${L} - 1`
  AFTER=`expr ${L} + 0`

  #echo "LLINE=$L"
  #echo "INSERTAT=$INSERTAT"
  #echo "AFTER=$AFTER"

  head -${INSERTAT} namei.c.2 > namei.c
  echo "	dentry->d_op = &ext3ci_dentry_operations;" >> namei.c
  tail -n +${AFTER} namei.c.2 >> namei.c
  cp namei.c namei.c.2
done

echo "Lowercase super.c"

# LINE=`cat -n super.c | grep 'struct super_block . ext3ci_read_super' | \
#	 awk '{ print $1 }'`
LINE=`cat -n super.c | grep 'static int ext3ci_fill_super' | \
	 awk '{ print $1 }'`
INSERTAT=`expr ${LINE} - 1`
AFTER=`expr ${LINE} + 0`

head -${INSERTAT} super.c > super.c.2
echo "extern struct dentry_operations ext3ci_dentry_operations;" >> super.c.2
tail -n +${AFTER} super.c >> super.c.2

LINE=`cat -n super.c.2 | \
	grep 'ext3ci_setup_super (sb, es, sb->s_flags . MS_RDONLY);' | \
	 awk '{ print $1 }'`
INSERTAT=`expr ${LINE} + 0`
AFTER=`expr ${LINE} + 1`

head -${INSERTAT} super.c.2 > super.c
echo "	sb->s_root->d_op = &ext3ci_dentry_operations;" >> super.c
tail -n +${AFTER} super.c.2 >> super.c

if [ -f Kconfig ] ;then
 echo "FIX Kconfig"
 sed '
	s/EXT3_/EXT3CI_/g
	s/Ext3 /Ext3 Case Insensitive /g
     ' Kconfig > Kconfig.2
 mv Kconfig.2 Kconfig
 grep -v ext3ci ../Kconfig > ../Kconfig.2
 EXT3CISTART=`cat -n ../Kconfig.2 |grep 'source "fs/ext3/Kconfig"' \
	| head -1 | awk '{ print $1 }'`
 AFTER=`expr ${EXT3CISTART} + 1`
 head -${EXT3CISTART} ../Kconfig.2 > ../Kconfig
 echo 'source "fs/ext3ci/Kconfig"' >> ../Kconfig
 tail -n +${AFTER} ../Kconfig.2 >> ../Kconfig
else 
echo "FIX ../Kconfig.in"
# Fix fs/Config.in so that ext3ci can be included in the kernel

EXT3CISTART=`cat -n ../Kconfig |grep '	config ' | cat -n |grep EXT3CI | head -1`
if [ "$EXT3CISTART" != "" ] ; then
  AFTER=`echo $EXT3CISTART | awk '{ print $1 }'`
  EXT3CIEND=`cat -n ../Kconfig |grep '	config ' |tail -n +${AFTER} | grep -v EXT3CI | head -1 | awk '{ print $1 }'`
  EXT3CISTART=`echo $EXT3CISTART | awk '{ print $2 }'`
  EXT3CISTART=`expr $EXT3CISTART - 1`
  head -${EXT3CISTART} ../Kconfig > ../Kconfig.2
  tail -n +$EXT3CIEND ../Kconfig >> ../Kconfig.2
  mv ../Kconfig.2 ../Kconfig
fi

EXT3START=`cat -n ../Kconfig |grep '	config ' | cat -n |grep EXT3 | head -1`
AFTER=`echo $EXT3START | awk '{ print $1 }'`
EXT3END=`cat -n ../Kconfig |grep '	config ' |tail -n +${AFTER} | grep -v EXT3 | head -1 | awk '{ print $1 }'` 
EXT3START=`echo $EXT3START | awk '{ print $2 }'`
NUMLINES=`expr $EXT3END - $EXT3START`
EXT3END=`expr $EXT3END - 1`
head -$EXT3END ../Kconfig > ../Kconfig.2
tail -n +$EXT3START ../Kconfig |head -$NUMLINES | sed '
	s/EXT3_FS/EXT3CI_FS/g
	s/Ext3 /Ext3 Case Insensitive /g
	' >> ../Kconfig.2
tail -n +$EXT3END ../Kconfig >> ../Kconfig.2
mv ../Kconfig.2 ../Kconfig
fi

echo "FIX ../Makefile"
# Fix fs/Makefile so that ext3ci can be included in the kernel
grep -v 'CONFIG_EXT3CI_FS' ../Makefile > ../Makefile.2
LINE=`cat -n ../Makefile.2 | grep 'CONFIG_EXT3_FS' | awk '{ print $1 }'`
INSERTAT=`expr ${LINE}`
AFTER=`expr ${LINE} + 1`

head -${INSERTAT} ../Makefile.2 > ../Makefile.3
# echo "subdir-\$(CONFIG_EXT3CI_FS)	+= ext3ci" >> ../Makefile.3
echo "obj-\$(CONFIG_EXT3CI_FS)		+= ext3ci/" >> ../Makefile.3
tail -n +${AFTER} ../Makefile.2 >> ../Makefile.3

mv ../Makefile.3 ../Makefile




