#!/bin/sh

# Config options

. /etc/lsbdev/lsbdev.conf

# Directory structure to precreate in chroot environment
REQUIRED_DIRS="usr/bin var/tmp bin lib proc tmp etc usr/lib/gcc-lib usr/lib/lsb-stub dev usr/include opt usr/sbin usr/lib/lib-localsystem var/run"

# End of configurable parameters
#
#----------------------------------------------------------------------
# Helper functions
bind_mount_ro()
{
  # At least for 2.4.5 kernels read only doesn't work
  mount -o ro --bind $1 $2
}

bind_mount_rw()
{
  # At least for 2.4.5 kernels read only doesn't work
  mount --bind $1 $2
}

bind_mount_file_ro()
{
  mkdir -p `dirname $2`
  if [ ! -e $2 ]; then
    touch $2
  fi
  mount --bind $1 $2
}

remove_old_mounts()
{
  mount_dirs=`cut -d' ' -f2 /proc/mounts  | grep $ROOT | sort -r`
  if [ "$mount_dirs" ]; then
    umount $mount_dirs
    if [ $? -ne 0 ]; then
      echo "Unmount failed. Aborting setup"
      exit 1
    fi
  fi
}


setup_home_dirs()
{
# Won't currently work with NIS
  for user in $BUILDUSERS; do
    homedir=`grep $user: /etc/passwd | cut -f6 -d:`
    if [ ! $homedir ]; then
      echo "Failed to get home directory for $user. Skipping user $user"
    else
      mkdir -p $ROOT$homedir
      bind_mount_rw $homedir $ROOT$homedir
    fi
  done;
}

process_system_mount_dirs()
{
  while read -r from_dir to_dir; do
    echo "$from_dir" | grep '^#' - > /dev/null
    if [ $? -ne 0 -a -n "$from_dir" ]; then
      if [ -z "$to_dir" ]; then
        echo "Error in config file: $from_dir"
      else 
        if [ -d "$from_dir" ]; then
          mkdir -p "$ROOT$to_dir"
          bind_mount_rw "$from_dir" "$ROOT$to_dir"
        else
          echo "Source directory is not a directory: $from_dir"
        fi
      fi
    fi
  done
}


process_system_mount_files()
{
  while read -r from_file to_file; do
    echo "$from_file" | grep '^#' - > /dev/null
    if [ $? -ne 0 -a -n "$from_file" ]; then
      if [ -z "$to_file" ]; then
        echo "Error in config file: $from_file"
      else 
        if [ -f "$from_file" ]; then
          bind_mount_file_ro "$from_file" "$ROOT$to_file"
        else
          echo "Source file is not a file: $from_file"
        fi
      fi
    fi
  done
}

create_ld_script()
{
  cat > $ROOT/usr/lib/lsb-stub/$1.so <<EOF
/* Autogenerated. Do not edit */
GROUP ( /usr/lib/lsb-stub/${lib}_shared.so /usr/lib/lsb-stub/${lib}_static.a )
EOF
}

import_static_lib()
{
  for libpath in $STATIC_LIB_SEARCH_PATH; do
    if [ -f $libpath/$1.a ]; then
      static_lib=$libpath
      break;
    fi
  done
  if [ "$static_lib" ]; then
    bind_mount_file_ro $static_lib/$1.a $ROOT/usr/lib/lsb-stub/${lib}_static.a
  else
    echo Warning. Could not find static library $lib.a
  fi
}

setup_stub_libraries()
{
  if [ "$FALLBACK_STATIC_LINK_LIBRARIES" ]; then
    for lib in $FALLBACK_STATIC_LINK_LIBRARIES; do
      create_ld_script $lib
      bind_mount_file_ro $STUB_LIBS/$lib.so $ROOT/usr/lib/lsb-stub/${lib}_shared.so
      import_static_lib $lib
      eval fs_$lib=1
    done
  fi

  # Import shared stub libraries
  for lib in $STUB_LIBRARY_LIST; do
    if [ -z "`eval echo \\$fs_\$lib`" ]; then
      bind_mount_file_ro $STUB_LIBS/$lib.so $ROOT/usr/lib/lsb-stub/$lib.so
    fi
  done

  # Special case for statically linked components of libc shared library.
  # and the 'real' libc shared library as libc.so is an ld script
  bind_mount_file_ro /usr/lib/libc_nonshared.a $ROOT/usr/lib/lsb-stub/libc_nonshared.a
  bind_mount_file_ro $STUB_LIBS/libc.real.so $ROOT/usr/lib/lsb-stub/libc.real.so

}


#----------------------------------------------------------------------
# Main bit

if [ `id -u` -ne 0 ]; then
  echo You must run this script as root
  echo Aborting.
  exit 1
fi

# Cleanup old build environment
if [ -e $RUNFILE ]; then
  echo Build environment is already setup. Aborting.
  echo If this is not the case remove $RUNFILE and try again.
  exit 1
else
  touch $RUNFILE
fi

# Setup build environment
# Make the required directory structure
for newdir in $REQUIRED_DIRS; do
  mkdir -p $ROOT/$newdir
done

# Setup bind mounts

# Basic structure
bind_mount_ro /bin $ROOT/bin 
bind_mount_ro /usr/bin $ROOT/usr/bin
bind_mount_ro /lib $ROOT/lib 
bind_mount_ro /proc $ROOT/proc
bind_mount_rw /tmp $ROOT/tmp
bind_mount_ro /var/tmp $ROOT/var/tmp
bind_mount_ro /etc $ROOT/etc
bind_mount_ro /dev $ROOT/dev
bind_mount_ro /usr/lib $ROOT/usr/lib/lib-localsystem

# Compiler stuff
bind_mount_ro /usr/lib/gcc-lib $ROOT/usr/lib/gcc-lib

# This section does bind mounts on libraries required
# for the compilation system (these are not LSB runtime needs)
# Needs to be updated in step with /etc/lsbdev/lsbdev.conf
if [ x$LIBBFD != x ]; then
  bind_mount_file_ro $LIBBFD $ROOT$LIBBFD
fi
if [ x$LIBOPCODES != x ]; then
  bind_mount_file_ro $LIBOPCODES $ROOT$LIBOPCODES
fi

bind_mount_file_ro /usr/lib/crt1.o $ROOT/usr/lib/crt1.o
bind_mount_file_ro /usr/lib/crti.o $ROOT/usr/lib/crti.o
bind_mount_file_ro /usr/lib/crtn.o $ROOT/usr/lib/crtn.o



# LSB linker
# Just copy the normal linux linker at the moment
# Can't bind mount symlinks in 2.4.5
# Use ld-lsb.so.1 preferentially
native_arch=`uname -m`
case $native_arch in
  i386|i486|i586|i686|athlon)
        NATIVE_LINKER=/lib/ld-linux.so.2
        LSB_LINKER=/lib/ld-lsb.so.1
        ;;
  ia64)
        NATIVE_LINKER=/lib/ld-linux-ia64.so.2
        LSB_LINKER=/lib/ld-lsb-ia64.so.1
        ;;

  *)
        echo "Unknown architecture $native_arch"
        exit 1
        ;;
esac

# Use LSB linker preferentially if it exists on the system
if [ -f $LSB_LINKER ]; then
    NATIVE_LINKER=$LSB_LINKER
fi

if [ ! -f $NATIVE_LINKER ]; then
    echo "Could not find file $NATIVE_LINKER"
    exit 1
fi

bind_mount_file_ro $NATIVE_LINKER $ROOT$LSB_LINKER

# copy GCC specs. modify copy to use lsb linker and lsb libraries
sed -e "s,\(dynamic-linker \)[^}]*\(.*\)$,\1$LSB_LINKER\2 -L /usr/lib/lsb-stub," $GCC_SPECS_FILE > $DATA_ROOT/gcc.specs.modified
bind_mount_file_ro $DATA_ROOT/gcc.specs.modified $ROOT/$GCC_SPECS_FILE

# Home directories
setup_home_dirs

# rpm
mkdir -p $ROOT$RPM_INSTALL_ROOT
bind_mount_rw $RPM_DATA_ROOT $ROOT$RPM_INSTALL_ROOT
if [ -e $ROOT/usr/bin/rpm ]; then
  # overlay the rpm we want
  bind_mount_file_ro $RPM_BIN $ROOT/usr/bin/rpm
fi
# lsb-rpm source dir
bind_mount_rw $RPM_SRC $ROOT$RPM_SRC

# Stub libraries
setup_stub_libraries

# Include Standard Header files
if [ -z "$LSB_INCLUDE" ]; then
    # If no header files are available then use the ones
    # installed on the system
    echo Warning. No LSB header files available. Using system include
    echo files. The binaries produced may not be LSB compliant.
    LSB_INCLUDE=/usr/include
fi
bind_mount_ro $LSB_INCLUDE $ROOT/usr/include

# System specific mounts
if [ -f "$EXTRA_MOUNT_DIRS" ]; then
  process_system_mount_dirs < "$EXTRA_MOUNT_DIRS"
fi

if [ -f "$EXTRA_MOUNT_FILES" ]; then
  process_system_mount_files < "$EXTRA_MOUNT_FILES"
fi


# setup sshd if available and desired
if [ -x "$SSH_DAEMON" ]; then
  touch $ROOT$SSH_DAEMON
  bind_mount_ro $SSH_DAEMON $ROOT$SSH_DAEMON
  LD_LIBRARY_PATH=/usr/lib/lib-localsystem chroot $ROOT $SSH_DAEMON -p $SSH_PORT
fi

