#!/usr/bin/perl
use strict;
use warnings;

##--( usage )---------------------------------------------------------------------------##
sub usage {
   print STDERR "flist_by_inum.pl v 1.01 sort file list by device/ino \n";
   print STDERR "                 (c) 2007 W. Pilorz, GPL license  \n";
   print STDERR "Usage: flist_by_inum.pl [-0] < input_flist > sorted_flist \n";
   print STDERR "input_flist is a file containing files, one per line \n";
   print STDERR "If -0 is given, line separator is NULL byte \n";
}
##---------------------------------------------------------------------------( usage )--##

my $usenull = 0;

##--( process_ARGV )--------------------------------------------------------------------##
sub process_ARGV {
   my @argv;
   my $had_dada;
   for (@ARGV) {
      if ($had_dada) { push @argv, $_; next; }
      if (/^--$/) { $had_dada = 1; next; }
      if (/^-/) {
         if (/^--?h(elp)?$/i) { usage(); exit(4); }
         if (/^-0$/) { $usenull = 1; next; }
         die "ERR: Unexpected parameter $_, use -h for help\n";
      }
      push @argv, $_;
   }
   @ARGV = @argv;
}
##--------------------------------------------------------------------( process_ARGV )--##

##--( process_flists )------------------------------------------------------------------##
sub process_flists {
   local $/ = "\x00" if $usenull;
   my @flist;
   while(<>) {
      chomp; s/\r$//;
      push @flist, $_;
   }
   exit(0) if not @flist;
   # @flist is immutable from this point, we sort index table;
   my @aix; # index table
   my $ii;
   for ($ii=0; $ii < @flist; ++$ii) { $aix[$ii] = $ii; }

   my @devno; # device number
   my @inum; # inode number
   for ($ii = 0; $ii < @flist; ++$ii) {
      my $fn = $flist[$ii];
      my @st = stat($fn);
      die "ERR: Could not stat file $fn: $!" if not @st;
      # now [0] is devno, [1] is ino, [7] is size
      $devno[$ii] = $st[0];
      $inum[$ii] = $st[1];
   }
   # sort index table
   @aix = sort { $devno[$a] <=> $devno[$b]
             ||  $inum[$a]  <=> $inum[$b]
             ||  $flist[$a] cmp $flist[$b] } @aix;
   my $sep = "\n"; $sep = "\x00" if $usenull;
   for (@aix) {
      print "$flist[$_]$sep";
   }
   close(STDOUT) or die "ERR: Could not write output file: $!";
}
##------------------------------------------------------------------( process_flists )--##


process_ARGV();
process_flists();

# vim:et sw=3 ts=3 smartindent
