#!/usr/bin/perl

#####################################################################
#
# fsetroot - initialize or clean up a mounted InterMezzo fileset
#
# Usage: fsetroot <start|stop>
#
#####################################################################

use strict;
use lib qw(/usr/lib/intermezzo);
use Lento::Psdev;

# Write newline-separated lines to a file.
sub setfile
{
    my ($filename, @lines) = @_;
    if (open (OUT, "> $filename"))
    {
    for (@lines)
    {
        print OUT $_, "\n";
    }
    close (OUT);
    }
}

#####################################################################
#
# Determine if we're starting or stopping the mounted fs's
#
#####################################################################

my $action = shift @ARGV;

if (not defined $action or
    ($action ne "start" and $action ne "status" and $action ne "stop")) {
  die "Usage: fsetroot <start|status|stop>\n";
}

#####################################################################
#
# If we're starting, first mount the InterMezzo file systems listed
# in /etc/fstab.
#
#####################################################################

# See if we have the proc mount file.
my $mountfile = '/proc/fs/intermezzo/mounts';
my $have_mounts = 0;
my %lines = ();
if (open (MOUNTS, "< $mountfile"))
{
    $have_mounts = 1;
}

if ($action eq 'start' || ! $have_mounts) {
    if (! -f "/etc/fstab") {
    exit 0;
    }

    my $printed = 0;
    open FST, "</etc/fstab";
    while (<FST>) {
    s/\#.*$//;
    my ($dev, $mtpt, $type, $opts) = split;
    if (defined $dev and defined $mtpt and defined $type and
        $type eq "InterMezzo") {
        if ($action eq 'start')
        {
        print "Mounting InterMezzo file systems:" if not $printed;
        print "  $mtpt";
        `mount $mtpt`;
        $printed = 1;
        }

        if ($opts =~ /(^|,)prestodev=([^,]+)/)
        {
        # Add this entry to our list of presto devices.
        $lines{$2} = 0;
        }
    }
    }
    if ($printed) {
    print "\n";
    }
}

#####################################################################
#
# Loop through the mounted InterMezzo file systems, and process
# each one.  /proc/fs/intermezzo/mounts lists the mounted InterMezzo
# file systems, including the mount point and the device used to
# talk to the presto module.
#
#####################################################################

my $lookupuser = 'web';
my $sysdir= '/proc/sys/intermezzo';
my $devname = '/dev/intermezzo';
my $printed = 0;

if ($have_mounts)
{
    # Read the mountfile, since it is more efficient for determining
    # exactly which mounts are in use.
    for (<MOUNTS>)
    {
    # Save the line by device.
    $lines{$1} = $_ if (/^\S+\s+\S+\s+(\S+)/);
    }
    close (MOUNTS);
}
else
{
    # List all the potential InterMezzo devices.
    my $i = 0;
    my ($dev) = "/dev/intermezzo$i";
    while (-c $dev)
    {
    $lines{$dev} = 0;
    $dev = "/dev/intermezzo$i";
    $i ++;
    }
}

for (sort (keys (%lines))) {
  my ($dev) = $_;

  $::psdev = Lento::Psdev->new($dev);
  $::psdev->open();

  if (! $lines{$dev})
  {
      # Fetch the mountpoint from this device.
      $lines{$dev} = $::psdev->readmount ();
      next if ($lines{$dev} eq '');
  }

  if ($action eq 'status')
  {
      # Just show the mount lines.
      print "Available InterMezzo file systems:\n" if (! $printed);
      print "  $lines{$dev}";
      $printed = 1;
      next;
  }

  # We should now have a proper mount line.
  my ($fset, $mtpt) = split (/\s+/, $lines{$dev});
  if (not defined $fset or not defined $mtpt or not defined $dev) {
    die "Error, cannot determine file system parameters.\n";
  }

  if ($action eq "start") {
    #print "set fsetroot for fset = $fset, mtpt = $mtpt, dev = $dev\n";
    $::psdev->setfsetroot($mtpt, $fset, 1, 0x0);

    # comment out the following lines if you want to enable debugging
    # messages to be output to /var/log/messages
    my $devbase = $dev;
    $devbase =~ s:^.*/::;
    my $tracefile = "$sysdir/$devbase/trace";
    my $debugfile = "$sysdir/$devbase/debug";
    setfile ($tracefile, 0);
    setfile ($debugfile, 0);

    # make sure to set no_filter for these devices for now, and no_upcall
    my $filtfile = "$sysdir/$devbase/no_filter";
    my $upcfile = "$sysdir/$devbase/no_upcall";
    setfile ($filtfile, 1);
    setfile ($upcfile, 1);

    # set the UID of the user that has access to the files through
    # the web server.  The web server needs to be running as this user.
    my $uidfile = "$sysdir/presto_ilookup_uid";
    my ($name, $passwd, $uid) = getpwnam $lookupuser;
    if (defined $uid) {
    setfile ($uidfile, $uid);
    } else {
    my ($nname, $npasswd, $nuid) = getpwnam "nobody";
    setfile ($uidfile, $nuid) if defined $nuid;
    }
  } else {
      print "Unmounting InterMezzo file systems:" if not $printed;
      print "  $mtpt";
      #print "clear fsetroot for fset = $fset, mtpt = $mtpt, dev = $dev\n";
      $::psdev->clearfsetroot($mtpt);
      `sync; sync; umount $mtpt`;
      $printed = 1;
  }
};

if ($printed && $action ne 'status') {
    print "\n";
}

exit 0;

