#!/usr/bin/perl -s
# $Id: mk-find-ls,v 1.7.1.1 1994/01/07 00:47:34 rdwill Exp $
#
# PATH changed for perl and date according to the Linux fsstnd
#    Ralf Flaxa, Linux Support Team erlangen, 12.05.94
#
# $Log: mk-find-ls,v $
# Revision 1.7.1.1  1994/01/07  00:47:34  rdwill
#  modified for epix.rrze.
#
# Revision 1.7  1994/01/07  00:44:06  rdwill
#  fixed the 'date' bug, which showed up after 01.01.94...
#
# Revision 1.6  1993/07/29  22:51:58  rdwill
#  extensively rearranged command line switches and their handling;
#   obsoleted switches keep their semantics!
#  reversed order of date and size for readability.
#  fixed a feature of epix (using '/usr/bin/date' now).
#  improved output of time-stamps by examining the last-modification-
#   date directly, no longer pretending all files, which are older than
#   6 months have been last modified at midnight (as 'ls -l' will only
#   show us the year, NO time).
#  cheated with log message of revision 1.4.
#
# Revision 1.5  1993/06/29  00:55:36  rdwill
#  added error handling to gzip extension checking.
#  added switch '-other' to output ONLY permissions for "others" (as opposed
#   to user and group) freeing up 6 characters per line. the omitted
#   permissions could be useful to only a very small number of users anyway.
#
# Revision 1.4  1993/06/28  23:41:16  rdwill
#  added automatic gzip-extension checking.
#  introduced 'sortable-date', a new output format for time-stamps,
#   which is human readable and also easily sorted by time
#   (ascending/[descending: newest first]) via 'sort [-r] +1 -2 +3'.
#
# Revision 1.3  1993/06/18  01:14:32  rdwill
#  gzip(1) replaces compress(1) as default compressor.
#  capitalized most variable names.
#  improved location of overwrite warning.
#  eliminated self-references.
#  restricted output to minimum.
#  improved verbose message.
#  more (IMHO) pretty pinting.
#
# Revision 1.2  1993/06/18  01:02:22  rdwill
#  added 'help'-switch and message.
#  added switch to choose between gzip(1) and compress(1).
#  output is now sorted by name.
#  replaced explicit commands with variables and removed absolute paths.
#  pretty pinting (IMHO).
#  modified error messages.
#
#

chop( $C = `basename $0`);

if ( $help || $h ) {
  print <<EODQ, <<'EOSQ';

NAME
    $C - create a sort of listing

SYNOPSIS
    $C [options]

DESCRIPTION
    Create a comprehensive, recursive, sorted listing of all files and
    directories under the current one, both in compressed and uncompressed
    form.

OPTIONS
    -help         give this message and exit.
    -quiet        don't ask silly questions, just do it.
    -verbose      opposite of -quiet. [DEFAULT]
    -gzip         use GNU gzip(1) for maximum compression. [DEFAULT]
    -compress     use compress(1) for conservative compression
    -full-perms   output full permissions.
    -others-only  output only permissions for others. [DEFAULT]
    -sort-date    use sortable date. [DEFAULT]
    -ls-date      use ls-style date.
    -sloppy-time  include hour:minute of last modification date, but
                  print 5 blanks as modification time of files older than
                  6 months.
    -exact-time   dig out modification date for objects incompletly reported
                  by ls(1) (implies -time). [DEFAULT]
    -no-time      date only, no time.

VERSION
EODQ
    $Id: mk-find-ls,v 1.7.1.1 1994/01/07 00:47:34 rdwill Exp $

EOSQ

  exit( 1);
}

# Set DEFAULT
$Verbose = 1;
$OtherOnly = 1;
$PrintTime = 1;
$ExactTime = 1;
$SortableDate = 1;
$UseGzip = 1;

# the following (very simple) parameter checker modifies variables 
# without check of duplications, contradictions.
# If contradictory parameters are used the order of their appearance
# on the command line is insigificant. That parameter which is checked
# last in the 'if'-clauses wins.

# -quiet <==> -verbose
if ( $quiet || $q ) {
  $Verbose = 0;
}
if ( $verbose || $v ) {
  $Verbose = 1;
}

# -compress <==> -gzip
if ( $compress ) {
  $UseGzip = 0;
}
if ( $gzip ) {
  $UseGzip = 1;
}

# -full-perms <==> -others-only
if ( $full-perms || $perms ) {
  $OtherOnly = 0;
} 
if ( $others-only || $others ) {
  $OtherOnly = 1;
}

# -ls-date <==> -sort-date
if ( $ls-date ) {
  $SortableDate = 0;
}
if ( $sort-date ) {
  $SortableDate = 1;
}

# -no-time <==> -sloppy-time <==> -exact-time
if ( $no-time ) {
  $PrintTime = 0;
}
if ( $sloppy-time ) {
  $ExactTime = 0;
  $PrintTime = 1;
}
if ( $exact-time || $time ) {
  $ExactTime = 1;
  $PrintTime = 1;
}


# compression setup
if ( $UseGzip ) {
  $Gzip = 'gzip';
  $Gzip_opt = '-9f';

  # check suffix
  $Tmp = "/tmp/$C-$$";
  system( "cp $0 $Tmp")
  && die ( "$C: ERROR: cp (0): $!\n");
  system( "$Gzip $Gzip_opt $Tmp")
  && die ( "$C: ERROR: $Gzip: $!\n leftover in '$Tmp'.\n");
  if ( -r "$Tmp.gz" ) {
    $Gz = '.gz';
  } else {
    $Gz = '.z';
  }
  unlink( "$Tmp$Gz")
  || die( "$C: ERROR: unlink $Tmp$Gz: $!\n leftover in '$Tmp$Gz'.\n");

} else {
  $Gzip = 'compress';
  $Gzip_opt = '-f';
  $Gz = '.Z';
}

# utility setup
$Cp_preserve = 'cp -p';
$Find = 'find';
$Sort = 'sort';
$Date = '/bin/date';

# output variables
$Tmp = "/tmp/$C-$$";
$Res = "00-find-ls";

if ( $Verbose ) {
  print <<EOF;

$C will create two files in the current working directory. The
contents of which is roughly described by the following commands:

  % $Find . -ls | some-perl-code-to-remove-unwanted-information > $Res 
  % $Gzip -c $Res > $Res$Gz

Note:
  For further information use '$C -help'. If '$C' terminates
  ABNORMALLY, there might be a leftover in '$Tmp'!

EOF

  printf( "OK to do so? (Y/n) ");
  $Answer = <STDIN>;
  if ( $Answer =~ m:[nN].*: ) {
    $! = -1;
    die(" User abort.\n");
  } 

  if ( -f "$Res" || -f "$Res$Gz" ) {
    print( "Ok to overwrite old '$Res'? (Y/n) ");
    $Answer = <STDIN>;
    if ( $Answer =~ m:[nN].*: ) {
      $! = -1;
      die(" User abort.\n");
    } 
  }
}

open( FIND, "$Find . -ls | $Sort +10|")
|| die( "$C: ERROR: open find-pipe: $!\n");

open( RESULT, "> $Tmp")
|| die( "$C: ERROR: open scratch-file: $!\n");
select( RESULT);

$| = 1;

%Month = (
   'Jan','01', 'Feb','02', 'Mar','03', 'Apr','04', 'May','05', 'Jun','06',
   'Jul','07', 'Aug','08', 'Sep','09', 'Oct','10', 'Nov','11', 'Dec','12',
);

$ThisMonth = `$Date '+%m'`;
chop $ThisMonth;
$ThisYear = `$Date '+%y'`;
chop $ThisYear;
if ( $ThisYear == 0 ) {
  $LastYear = 99;
} else {
  $LastYear = $ThisYear - 1;
}

<FIND>;
while ( <FIND> ) {
  chop;
  s/^\s*//;
  ($Ino, $Blk, $Acc, $Lnk, $Uid, $Gid, $Siz, $Mo, $Da, $T_Y, $N, @Rst) = split;
  $N =~ s/\.\///;
  if ( "$N" eq "$Res" || "$N" eq "$Res$Gz" ) {
    next;
  }
  if ( $OtherOnly ) {
    $Acc =~ s/(.)......(...)/$1$2/;
  }
  if ( $SortableDate ) {
    if ( $T_Y =~ /\d\d\:\d\d/ ) {
      if ( $Month{$Mo} <= $ThisMonth ) {
        $Year = $ThisYear;
      } else {
        $Year = $LastYear;
      }
      $Time = $T_Y;
    } elsif ( $T_Y =~ /19(\d\d)/ ) {
      $Year = $1;
      if ( $ExactTime ) {
        $Time = &getTime( $N);
      } else {
        $Time = "     ";
      }
    } else {
      # this should NEVER happen!
      $Year = '??';
      $Time = $T_Y;
    }
    if ( $PrintTime ) {
      printf("%s %s/%s/%02d-%s %7s %s @Rst\n",
         $Acc, $Year, $Month{$Mo}, $Da, $Time, $Siz, $N);
#     printf("%s %s%s%02dT%s %7s %s @Rst\n",
#        $Acc, $Year, $Month{$Mo}, $Da, $Time, $Siz, $N);
    } else {
      printf("%s %s%s%02d %7s %s @Rst\n",
         $Acc, $Year, $Month{$Mo}, $Da, $Siz, $N);
    }
  } else {
    printf("%s %9s  %s %2s %5s %s @Rst\n",
       $Acc, $Siz, $Mo, $Da, $T_Y, $N);
  }
}
 
close( FIND);
close( RESULT);

select( STDERR);
$| = 1;


system( "$Cp_preserve $Tmp $Res\n")
&& die ( "$C: ERROR: cp (1): $!\n");

system( "$Gzip $Gzip_opt $Res\n")
&& die ( "$C: ERROR: $Gzip: $!\n leftover in '$Tmp'.\n");

system( "$Cp_preserve $Tmp $Res\n")
&& die ( "$C: ERROR: cp (2): $!\n leftover in '$Tmp'.\n");

unlink( "$Tmp")
|| die( "$C: ERROR: unlink $Tmp: $!\n leftover in '$Tmp'.\n");


### Subroutines
sub getTime {
  local( $target) = @_;
  local( $mtime ) = (stat($target))[9];
  local( $sec, $min, $hour, @Rst) = localtime( $mtime);

# printf("** %s, %02d:%02d **", $mtime, $hour, $min);
  sprintf("%02d:%02d", $hour, $min);
}

sub getDate {
  local( $target) = @_;
  local( $mtime ) = (stat($target))[9];
  local( $sec, $min, $hour, @Rst) = localtime( $mtime);

# printf("** %s, %02d:%02d **", $mtime, $hour, $min);
  sprintf("%02d:%02d", $hour, $min);
}

