#       serial - serialize updates & support routines
#
# Copyright (c) 1993, 1994, 1995, 1996, 1997, 1998, 1999 by RIPE NCC
#
# All Rights Reserved
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose and without fee is hereby granted,
# provided that the above copyright notice appear in all copies and that
# both that copyright notice and this permission notice appear in
# supporting documentation, and that the name of the author not be
# used in advertising or publicity pertaining to distribution of the
# software without specific, written prior permission.
#
# THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
# AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
# AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#
# $Id: serial.pl,v 2.5 1999/10/06 16:41:20 marek Exp $
#
#	$RCSfile: serial.pl,v $
#	$Revision: 2.5 $
#	$Author: marek $
#	$Date: 1999/10/06 16:41:20 $

require "defines.pl";
require "dpr.pl";

# open a serial file
  
sub openandreadserial {
    local($extension,$logtext)=@_;
   
    local($filename)=$LOGFILE{"SERIALDIR"};
    $filename=$LOCKDIR if ($filename=~ /^\s*$/);
    $filename.=$extension;
   
    # print STDERR "ext: $extension log: $logtext\n";
   
    if (!open(SERIAL,"+<".$filename)) {
      
      if (-f $filename) {
         &fatalerror($logtext." - cannot open serial file in: ".$filename);
      }
      else {
         
         # don't do a destructive open since we are not locked yet
         
         open(SERIAL,">>".$filename) || &fatalerror($logtext." - cannot create new serial file: ".$filename);
         
         &lock(SERIAL);
         
         # another process might have build it between the open & lock...
         # so test if the file has still zero length!
         #
         # we could have done this with other flock options
         # but we don't want to use them for compatibility reasons
         
         local($oldestextensionregular)=&MakeRegular($OLDESTEXTENSION);
         
         if ($extension=~ s/$oldestextensionregular$//) {
            
            close(SERIAL);
            
            # print STDERR "oldest source: $extension\n";
            
            local($currentserial)=&getcurrentserial($extension)+1;
            
            local($serialfile, $serial)=&openandreadserial($extension.$OLDESTEXTENSION, "openandreadserial current");
            print $serialfile $currentserial if (-z $filename);
            close($serialfile);
            
         }
         else {                                   
            print SERIAL 0 if (-z $filename);
            close(SERIAL);
            
            #
            # and make the oldest also
            
            local($currentextensionregular)=&MakeRegular($CURRENTEXTENSION);
            $extension=~ s/$currentextensionregular$//;
            # print STDERR "current source: $extension\n";
            local($serialfile, $serial)=&openandreadserial($extension.$OLDESTEXTENSION, "openandreadserial oldest");
            close($serialfile);
         
         }
         
         open(SERIAL,"+<".$filename) || &fatalerror($logtext." - cannot open serial file after creation: ".$filename);
      
      }
   
   }
   
   &lock(SERIAL) || &fatalerror($logtext." - cannot lock serial file($!): ".$filename);
   
   return (SERIAL, <SERIAL>=~ /^\s*(\d+)\s*$/);
   
}


sub getcurrentserial {
   local($source)=@_;

   local($serialfile, $serial)=&openandreadserial($source.$CURRENTEXTENSION, "getcurrentserial");
   
#   &dpr("CurrentSerial: *$serial*\n");
   
   close($serialfile) || &fatalerror("getcurrentserial - cannot close/unlock serial file");
    
   return $serial;
}

sub getoldestserial {
   local($source)=@_;

   local($serialfile, $serial)=&openandreadserial($source.$OLDESTEXTENSION, "getoldestserial");
   
#   &dpr("OldestSerial: *$serial*\n");
   
   close($serialfile) || &fatalerror("getoldestserial - cannot close/unlock serial file");
   
   return $serial;

}


sub writeseriallog {
   local($transaction, *en)=@_;
   
   # print STDERR %en, "\n";
   
   local($serialfile, $serial)=&openandreadserial($en{"so"}.$CURRENTEXTENSION, "writeseriallog");
   
   # and update it ...
   
   seek($serialfile,0,0);
   $serial++;
   print $serialfile $serial;
   
   # only write the entry when the serial dir is specified
   
   # note: we don't want to propagate the limericks for now...
   
   if ($LOGFILE{"SERIALDIR"}!~ /^\s*$/) {
      
      open(SERIALDATA,">".$LOGFILE{"SERIALDIR"}.$en{"so"}.".".$serial) || &fatalerror("writeseriallog - cannot open serial data file: ".$LOGFILE{"SERIALDIR"}.$en{"so"}.".".$serial);
      
      &lock(SERIALDATA) || &fatalerror("writeseriallog - cannot lock serial data file: ".$LOGFILE{"SERIALDIR"}.$en{"so"}.".".$serial);
   
      close($serialfile) || &fatalerror("writeseriallog - cannot close/unlock serial file: ".$LOGFILE{"SERIALDIR"}.$en{"so"}.$CURRENTEXTENSION);
   
      #
      # write the entry
      
      print SERIALDATA $transaction."\n";

      &enwrite(SERIALDATA,*en,0,0,0);
      
      close(SERIALDATA) || &fatalerror("writeseriallog - cannot close/unlock serial data file: ".$LOGFILE{"SERIALDIR"}.$en{"so"}.".".$serial);
      
   }
   else {

      close($serialfile) || &fatalerror("writeseriallog - cannot close/unlock serial file: ".$LOGFILE{"SERIALDIR"}.$en{"so"}.$CURRENTEXTENSION);

   }
   
   return $serial;
   
}

1;
