#!/usr/bin/perl

use Cwd "abs_path";
# /usr/share -> /home/shadow.filesystem/usr/share
# /usr/lib -> /home/shadow.filesystem/usr/lib

# /home/shadow.filesystem/usr/lib/libcairo.so.2.10800.6 => 
#  /usr/.lib/libcairo.so.2.10800.6

my $shadow_root = '/home/shadow.filesystem';
my %map = ();

sub mkdir_recurse
{
  my $path = shift;
  my @dirs = split m!/!, $path;
  $path = "";
  foreach my $dir (@dirs) {
    next unless $dir ne '';
    $path .= "/$dir";
    mkdir $path;
  }
}

sub try_mkdir
{
  my ($orig, $dir) = @_;
  mkdir_recurse($dir) unless -d $dir;
  $map{$orig} = $dir;
}

sub map_path
{
  my $path = shift;
  $path =~ s!^(/usr/)!$1.!;
  return $path;
}

sub copy_link
{
  my ($real_path, $symlink) = @_;
  my $target = map_path(abs_path($real_path));
  symlink($target, $symlink);
}

sub create_link
{
  my ($real_path, $symlink) = @_;
  my $target = map_path(abs_path($real_path));
  symlink($target, $symlink);
}

sub create_shadow_tree
{
  my @dirs = @_;
  foreach my $dir (@dirs) {
    try_mkdir($dir, $shadow_root . $dir);
  }
}

sub create_links
{
  my ($dir, $shadow) = @_;
  return unless opendir(HANDLE, $dir);
  my @items = readdir(HANDLE);
  closedir(HANDLE);
  foreach my $item (@items) {
    next if $item eq '.' || $item eq '..';
    my $path = $dir . '/' . $item;
    my $shadow_path = $shadow_root . $path;
    if (-l $path) {
      copy_link($path, $shadow_path);
    } elsif (-d $path) {
      try_mkdir($shadow_path);
      create_links($path, $shadow_path);
    } elsif (-f $path) {
      create_link($path, $shadow_path);
    }
  }
}

sub mirror_tree
{
  my @dirs = @_;
  foreach my $dir (@dirs) {
    create_links($dir, $shadow_root . $dir);
  }
}

if (1) {
  my @dirs = ('', '/usr', '/usr/share', '/usr/lib');
  create_shadow_tree(@dirs);
  @dirs = ('/usr/share', '/usr/lib');
  mirror_tree(@dirs);
  foreach my $dir (@dirs) {
    symlink($shadow_root.$dir, $dir.'~');
  }
  foreach my $dir (@dirs) {
    rename($dir, map_path($dir);
    rename($dir.'~', $dir);
  }
}

