HowTo install SuSE Linux chrooted

I have an old game, Civilization Call to Power, that did not run on my current system. As the distributor of the Linux version, Loki Entertainment Software, no longer exists, I could get no support from there. Luckily they packaged a SuSE 6.1 Evaluation Version CD with the game. That is the software from the era (mid 1999), so I supposed that should work.

But I did not feel like dedicating a partition to SuSE and rebooting just to play this game. I don't suppose the old Kernel could cope with my SATA drive anyway. So I tried to get SuSE installed into a directory of my system and to run programs chrooted in this directory. Here is a summary of the tricks that got me there. I cannot guarantee completeness, but I'll try my best.

1. Copy the installation system

First you need to get the Environment SuSE ist using for the installation. You find it in the directory suse/inst-sys/ of the CD-ROM. Copy this whole directory to your hard drive.

2. Prepare target device

I could only get the installation process to do the initial installation on a block device. Of course I don't want to use a real partition; instead I'm using a loop device.

First create a file that will receive the installation file system. I created a 256MiB file using this command: dd if=/dev/zero of=loopdev bs=64k count=4096.

Then you can associate the loop device with this file using losetup /dev/loop0 loopdev. Now /dev/loop behaves almost like a normal partition, but the data is actuallay stored in the file loopdev.

You can now create an Ext2 file system on this device: mke2fs /dev/loop0.

3. Faking fdisk

The SuSE setup tool YaST tries to be clever and would not let you specify a target device for the installation. Instead it asks fdisk -l to display a list of partitions and parses this result.

The simplest way to avoid this is by replacing the fdisk command of the installation environment with a simple script that outputs a hard coded result. The command called by YaST is stored in a directory of its own, its path is inst-sys/usr/lib/YaST/fdisk.

I derived the geometry of the loop device from fdisk -l /dev/loop0, the format of a partition list from fdisk -l and the size of the loop device in blocks from /proc/partitions. The result was included in my replacement for inst-sys/usr/lib/YaST/fdisk. Remember to set execute permission on this file once you have created it.

#!/usr/sh
if [ "$*" = "-l" ]; then
  echo ""
  echo "Disk /dev/hda: 67 MB, 67108864 bytes"
  echo "255 heads, 63 sectors/track, 8 cylinders"
  echo "Units = cylinders of 16065 * 512 = 8225280 bytes"
  echo ""
  echo "   Device Boot      Start         End      Blocks   Id  System"
  echo "/dev/hda1   *           1           8       65536   83  Linux"
else
  exec /sbin/fdisk "$@"
fi

4. Populate the installation system

Next you need to make the setup environment to look real enough. You mount the proc file system there as well: mount --bind /proc $PWD/inst-sys/proc.

You have to populate the dev directory as well. copy -RLp /dev/null /dev/zero /dev/tty inst-sys/dev/. As you can see in the fake partition list above, I decided to have my partition named hda1. So I rename the loop device: copy -RLp /dev/loop0 inst-sys/dev/hda1.

To access the instalation CD in the chrooted environment, you should probably mount it before you start installation, by issuing mount /dev/cdrom $PWD/inst-sys/cdrom.

5. Run installation

By issuing chroot inst-sys YaST, you can start the installation. You should probably do this from a text console, as I had trouble using F4 to set a mount point in xterm.

The installation is straightforward. As your instalation medium you select a reachable directory, namely /cdrom. Choose not to repartition any drives, set the mount point of the only listed partition /dev/hda1 to /. You can choose very few packages for now, as you can always add more later on when you are out of the loop device and in a native directory of your host system. You can save a lot of space by dispensing with the kernel sources. Don't build any boot disks, as you won't have to boot this system.

Once installation is complete, you can unmount your auxiliary mounts: umount $PWD/inst-sys/cdrom and umount $PWD/inst-sys/proc.

6. Moving from loop device to directory

Mount the loop device to some available mount point in your system: mount /dev/loop0 $PWD/inst-sys/mnt. Now you can copy the installed system out of this device: cp -pR inst-sys/mnt SuSE. Then you won't need the loop device any longer, you can unmount it using umount /dev/loop0 and disassociate the loop device using losetup -d /dev/loop0. You can even remove the backing file and installation environment: rm -r loopdev inst-sys.

To have your device permissions only in one place, it is probably a good idea to remove the dev directory of the installed system. rm -r SuSE/dev

7. Using the system

To use this system, you should first mount --bind /proc $PWD/SuSE/proc and mount --bind /dev $PWD/SuSE/dev. Then you can Enter your new system using chroot SuSE bash --login or something similar. If you want to drop root privileges in the chroot, you first should make sure that appropriate users exist there, by examining SuSE/etc/passwd and SuSE/etc/group. Then you can use su - UserName to temporarily drop root privileges.

8. X11 connection

If you want to access an X11 server running outside the chroot, you have to take care of three things. The first is authentication information. This is stored in the file .Xauthority in the home directory of the user. Copy this file to the matching home directory inside the SuSE directory, but take care of file permissions and ownership.

The other thing is the unix domain socket used to communicate with the server. Usually for your primary display this is /tmp/.X11-unix/X0. You can create an empty file inside the chroot and then bind it using mount --bind /tmp/.X11-unix/X0 SuSE/tmp/.X11-unix/X0. To connect you have to make sure that the DISPLAY environment variable inside the chroot is the same as outside, usually DISPLAY=:0.0.

Using this installation, I was able to run the game and have a look at the atimes of the system libraries. In this way I identified which libraries are used by the game, and could provide a rather convenient description on how to fix the original problem.