Config::Manager::File - Basic File Utilities (for Tools)


Config-Manager documentation Contained in the Config-Manager distribution.

Index


Code Index:

NAME

Top

Config::Manager::File - Basic File Utilities (for Tools)

SYNOPSIS

Top

  use Config::Manager::File
  qw(
        Normalize
        MakeDir
        UniqueTempFileName
        ConvertFromHost
        ConvertToHost
        CompareFiles
        CopyFile
        MoveByCopying
        MD5Checksum
        ReadFile
        WriteFile
        AppendFile
        ConvertFileWithCallback
        SerializeSimple
        Semaphore_Passeer
        Semaphore_Verlaat
        GetNextTicket
  );

  use Config::Manager::File qw(:all);

  $dir = Normalize($dir);

  ($drv,$dir) = Normalize($dir);

  $error = MakeDir($dir);

  $tempfilename = &UniqueTempFileName();

  &ConvertFromHost($targetfile,$sourcefile,$linenumbering,$purgeblanks);

  &ConvertToHost($targetfile,$sourcefile,$linenumbering,$purgeblanks,$checklength);

  $same = &CompareFiles($file1,$file2);

  &CopyFile($source,$target);

  &MoveByCopying($source,$target);

  $checksum = &MD5Checksum($source);

  $arrayref = &ReadFile($source);

  &WriteFile($target,@contents);

  &AppendFile($target,$source);

  &ConvertFileWithCallback($target,$source,$callback);

  $printable = &SerializeSimple("varname",$datastructure);

  Semaphore_Passeer($lockfile);

  Semaphore_Verlaat($lockfile);

  $ticket = GetNextTicket($lockfile,$ticketfile,$count_min,$count_max);

DESCRIPTION

Top

SEE ALSO

Top

Config::Manager(3), Config::Manager::Base(3), Config::Manager::Conf(3), Config::Manager::PUser(3), Config::Manager::Report(3), Config::Manager::SendMail(3), Config::Manager::User(3).

VERSION

Top

This man page documents "Config::Manager::File" version 1.7.

AUTHORS

Top

 Steffen Beyer <sb@engelschall.com>
 http://www.engelschall.com/u/sb/download/
 Gerhard Albers

COPYRIGHT

Top

LICENSE

Top

This package is free software; you can use, modify and redistribute it under the same terms as Perl itself, i.e., under the terms of the "Artistic License" or the "GNU General Public License".

Please refer to the files "Artistic.txt" and "GNU_GPL.txt" in this distribution, respectively, for more details!

DISCLAIMER

Top

This package is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

See the "GNU General Public License" for more details.


Config-Manager documentation Contained in the Config-Manager distribution.

###############################################################################
##                                                                           ##
##    Copyright (c) 2003 by Steffen Beyer & Gerhard Albers.                  ##
##    All rights reserved.                                                   ##
##                                                                           ##
##    This package is free software; you can redistribute it                 ##
##    and/or modify it under the same terms as Perl itself.                  ##
##                                                                           ##
###############################################################################

package Config::Manager::File;

use strict;
use vars qw( @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS $VERSION );

require Exporter;

@ISA = qw(Exporter);

@EXPORT = qw();

@EXPORT_OK = qw(
    Normalize
    MakeDir
    UniqueTempFileName
    ConvertFromHost
    ConvertToHost
    CompareFiles
    CopyFile
    MoveByCopying
    MD5Checksum
    ReadFile
    WriteFile
    AppendFile
    ConvertFileWithCallback
    SerializeSimple
    Semaphore_Passeer
    Semaphore_Verlaat
    GetNextTicket
);

%EXPORT_TAGS = (all => [@EXPORT_OK]);

$VERSION = '1.7';

use Symbol;
use Fcntl qw(:DEFAULT :flock);

use Config::Manager::Base qw( $SCOPE );
use Config::Manager::Conf;
use Config::Manager::Report qw(:ALL); # also import Normalize and MakeDir
use File::Compare;
use File::Copy;
use Digest::MD5;

#######################################
## Internal configuration constants: ##
#######################################

my @TEMPDIR = ('DEFAULT', 'TEMPDIRPATH');
my @MAXLEN  = ('COBOL',   'Maximum_Line_Length');

my $DEFAULT_MAXLEN = 66;

my $TMPEXT = 'tmp';

#######################
## Static variables: ##
#######################

my $Counter = 0;
my @TempFileList = ();

########################
## Private functions: ##
########################

END
{
    my($file);
    foreach $file (@TempFileList)
    {
        if (-f $file and not unlink($file))
        {
            print STDERR "Please remove temporary file '$file' manually: $!\n";
        }
    }
}

#######################
## Public functions: ##
#######################

# sub Normalize; # imported from Config::Manager::Report

# sub MakeDir;   # imported from Config::Manager::Report

sub UniqueTempFileName
{
    my($path,$error,$file);

    unless (defined ($path = Config::Manager::Conf->get(@TEMPDIR)))
    {
        if ($^O =~ /Win32/i)
        {
            $path = $ENV{'TEMP'} || $ENV{'TMP'} || "C:\\Temp";
        }
        else
        {
            $path = $ENV{'TEMP'} || $ENV{'TMP'} || "/tmp";
        }
        $error = Config::Manager::Conf->error();
        $error =~ s!\s+$!!;
        Config::Manager::Report->report(@WARN,
            "Unable to determine directory for temporary files:",
            $error,
            "Using '$path' instead...");
    }
    $path =~ s![/\\]+$!!;
    $path .= "/$SCOPE";
    $file = sprintf
    (
        "%s_%03d%02d%02d%02d_%d_%d.%s",
        $path,
        (localtime(time))[7,2,1,0],
        $$,
        ++$Counter,
        $TMPEXT
    );
    push( @TempFileList, $file );
    return $file;
}

sub ConvertFromHost
{
    my($target,$source,$lines,$purge,$kludge) = @_;
    my($error,$line);
    local($/) = "\n";
    local($.);
    local($!);

    unless (-f $source && -s $source)
    {
        Config::Manager::Report->report(@ERROR,
            "File '$source' not found or empty");
        return undef;
    }
    unless (open(SOURCE, "<$source"))
    {
        Config::Manager::Report->report(@ERROR,
            "Can't read file '$source': $!");
        return undef;
    }
    unless (open(TARGET, ">$target"))
    {
        Config::Manager::Report->report(@ERROR,
            "Can't write file '$target': $!");
        unless (close(SOURCE))
        {
            Config::Manager::Report->report(@WARN,
                "Can't close file '$source': $!");
        }
        return undef;
    }
    $error = 0;
    while (defined ($line = <SOURCE>))
    {
        if ($purge) { $line =~ s!\s+$!!; }
        else        { $line =~ s![\x0D\x0A]+$!!; }
        if ($lines)
        {
            $error = 1 unless ($line =~ s!^\d\d\d\d\d\d!!);
        }
        # Translate ÜíÖùä!üß => ![\]{|}~
        $line =~ tr/\xDC\xED\xD6\xF9\xE4\x21\xFC\xDF/\x21\x5B\x5C\x5D\x7B\x7C\x7D\x7E/ if ($kludge);
        print TARGET "$line\n";
    }
    if ($error)
    {
        Config::Manager::Report->report(@WARN,
            "There were lines not beginning with 6 digits in file '$source'!");
    }
    unless (close(TARGET))
    {
        Config::Manager::Report->report(@ERROR,
            "Can't close file '$target': $!");
        unless (close(SOURCE))
        {
            Config::Manager::Report->report(@WARN,
                "Can't close file '$source': $!");
        }
        return undef;
    }
    unless (close(SOURCE))
    {
        Config::Manager::Report->report(@WARN,
            "Can't close file '$source': $!");
    }
    return 1;
}

sub ConvertToHost
{
    my($target,$source,$lines,$purge,$check,$kludge) = @_;
    my($maxlen,$error,$line);
    local($/) = "\n";
    local($.);
    local($!);

    unless (-f $source && -s $source)
    {
        Config::Manager::Report->report(@ERROR,
            "File '$source' not found or empty");
        return undef;
    }
    unless (open(SOURCE, "<$source"))
    {
        Config::Manager::Report->report(@ERROR,
            "Can't read file '$source': $!");
        return undef;
    }
    unless (open(TARGET, ">$target"))
    {
        Config::Manager::Report->report(@ERROR,
            "Can't write file '$target': $!");
        unless (close(SOURCE))
        {
            Config::Manager::Report->report(@WARN,
                "Can't close file '$source': $!");
        }
        return undef;
    }
    if ($check)
    {
        unless (defined ($maxlen = Config::Manager::Conf->get(@MAXLEN)))
        {
            $maxlen = $DEFAULT_MAXLEN;
            $error = Config::Manager::Conf->error();
            $error =~ s!\s+$!!;
            Config::Manager::Report->report(@WARN,
                "Unable to determine maximum COBOL line length:",
                $error,
                "Using '$maxlen' instead...");
        }
    }
    $error = 0;
    while (defined ($line = <SOURCE>))
    {
        if ($purge) { $line =~ s!\s+$!!; }
        else        { $line =~ s![\x0D\x0A]+$!!; }
        if ($check && (length($line) > $maxlen))
        {
            $error = 1;
        }
        # Translate ![\]{|}~ => ÜíÖùä!üß
        $line =~ tr/\x21\x5B\x5C\x5D\x7B\x7C\x7D\x7E/\xDC\xED\xD6\xF9\xE4\x21\xFC\xDF/ if ($kludge);
        $line = sprintf("%05d0%s", $., $line) if ($lines);
        print TARGET "$line\n";
    }
    if ($error)
    {
        Config::Manager::Report->report(@WARN,
            "Maximum COBOL line length ($maxlen) exceeded in file '$source'!");
    }
    unless (close(TARGET))
    {
        Config::Manager::Report->report(@ERROR,
            "Can't close file '$target': $!");
        unless (close(SOURCE))
        {
            Config::Manager::Report->report(@WARN,
                "Can't close file '$source': $!");
        }
        return undef;
    }
    unless (close(SOURCE))
    {
        Config::Manager::Report->report(@WARN,
            "Can't close file '$source': $!");
    }
    return 1;
}

sub CompareFiles
{
    my($source,$target) = @_;
    my($rc);
    local($!);

    # returns true  (1) if both files have identical contents,
    #         false (0) if their contents differ,
    #     and undef     if there was any error.

    unless (-f $source)
    {
        Config::Manager::Report->report(@ERROR,
            "File '$source' does not exist!");
        return undef;
    }
    unless (-f $target)
    {
        Config::Manager::Report->report(@ERROR,
            "File '$target' does not exist!");
        return undef;
    }
    if (($rc = compare($source,$target)) < 0)
    {
        Config::Manager::Report->report(@ERROR,
            "Error while comparing files '$source' and '$target': $!");
        return undef;
    }
    return ($rc == 0) ? 1 : 0;
}

sub CopyFile
{
    my($source,$target) = @_;
    local($!);

    unless (-f $source)
    {
        Config::Manager::Report->report(@ERROR,
            "File '$source' does not exist!");
        return undef;
    }
    unless (copy($source,$target))
    {
        Config::Manager::Report->report(@ERROR,
            "Error while copying file '$source' to '$target': $!");
        return undef;
    }
    return 1;
}

sub MoveByCopying
{
    my($source,$target) = @_;
    local($!);

    unless (-f $source)
    {
        Config::Manager::Report->report(@ERROR,
            "File '$source' does not exist!");
        return undef;
    }
    unless (copy($source,$target))
    {
        Config::Manager::Report->report(@ERROR,
            "Error while copying file '$source' to '$target': $!");
        return undef;
    }
    unless (unlink($source))
    {
        Config::Manager::Report->report(@ERROR,
            "Could not unlink file '$source': $!");
        return undef;
    }
    return 1;
}

sub MD5Checksum
{
    my($source) = @_;
    my($md5,$checksum);
    local($!);

    unless (-f $source)
    {
        Config::Manager::Report->report(@ERROR,
            "File '$source' does not exist!");
        return undef;
    }
    unless (open(SOURCE, "<$source"))
    {
        Config::Manager::Report->report(@ERROR,
            "Can't read file '$source': $!");
        return undef;
    }
    $md5 = Digest::MD5->new();
#   $md5->reset(); # obsolete, same as new()
    $md5->addfile(*SOURCE);
    $checksum = $md5->hexdigest();
    unless (close(SOURCE))
    {
        Config::Manager::Report->report(@WARN,
            "Can't close file '$source': $!");
    }
    return $checksum;
}

sub ReadFile
{
    my($source) = @_;
    my(@text);
    local($/) = "\n";
    local($!);

    unless (-f $source)
    {
        Config::Manager::Report->report(@ERROR,
            "File '$source' does not exist!");
        return undef;
    }
    unless (open(SOURCE, "<$source"))
    {
        Config::Manager::Report->report(@ERROR,
            "Can't read file '$source': $!");
        return undef;
    }
    @text = <SOURCE>;
    unless (close(SOURCE))
    {
        Config::Manager::Report->report(@WARN,
            "Can't close file '$source': $!");
    }
    return \@text;
}

sub WriteFile
{
    my($target) = shift;
    my($item,$line);
    local($!);

    unless (open(TARGET, ">$target"))
    {
        Config::Manager::Report->report(@ERROR,
            "Can't write file '$target': $!");
        return undef;
    }
    foreach $item (@_)
    {
        if (ref($item))
        {
            if (ref($item) eq 'ARRAY')
            {
                foreach $line (@{$item})
                {
                    print TARGET $line;
                }
            }
            else
            {
                Config::Manager::Report->report
                (
                    @FATAL,
        "Illegal parameter '$item': neither a SCALAR nor an ARRAY reference"
                );
                return undef;
            }
        }
        else
        {
            print TARGET $item;
        }
    }
    unless (close(TARGET))
    {
        Config::Manager::Report->report(@ERROR,
            "Can't close file '$target': $!");
        return undef;
    }
    return 1;
}

sub AppendFile
{
    my($target,$source) = @_;
    my($size,$buffer,$read,$offset,$written);
    local($!);

    unless (-f $source)
    {
        Config::Manager::Report->report(@ERROR,
            "File '$source' does not exist!");
        return undef;
    }
    unless (open(SOURCE, "<$source"))
    {
        Config::Manager::Report->report(@ERROR,
            "Can't read file '$source': $!");
        return undef;
    }
    unless (binmode(SOURCE))
    {
        Config::Manager::Report->report(@ERROR,
            "Can't set binmode for file '$source': $!");
        unless (close(SOURCE))
        {
            Config::Manager::Report->report(@WARN,
                "Can't close file '$source': $!");
        }
        return undef;
    }
    unless (open(TARGET, ">>$target"))
    {
        Config::Manager::Report->report(@ERROR,
            "Can't append to file '$target': $!");
        unless (close(SOURCE))
        {
            Config::Manager::Report->report(@WARN,
                "Can't close file '$source': $!");
        }
        return undef;
    }
    unless (binmode(TARGET))
    {
        Config::Manager::Report->report(@ERROR,
            "Can't set binmode for file '$target': $!");
        unless (close(SOURCE))
        {
            Config::Manager::Report->report(@WARN,
                "Can't close file '$source': $!");
        }
        unless (close(TARGET))
        {
            Config::Manager::Report->report(@WARN,
                "Can't close file '$target': $!");
        }
        return undef;
    }
    $size = -s SOURCE;
    $size = 1024 if ($size < 512);
    $size = 32768 if ($size > 32768);
    CYCLE:
    while (1)
    {
        unless (defined ($read = sysread(SOURCE,$buffer,$size)))
        {
            Config::Manager::Report->report(@ERROR,
                "Can't read from file '$source': $!");
            unless (close(SOURCE))
            {
                Config::Manager::Report->report(@WARN,
                    "Can't close file '$source': $!");
            }
            unless (close(TARGET))
            {
                Config::Manager::Report->report(@WARN,
                    "Can't close file '$target': $!");
            }
            return undef;
        }
        last CYCLE unless ($read > 0);
        for ( $offset = 0; $offset < $read; $offset += $written )
        {
            unless (defined ($written = syswrite(TARGET,$buffer,$read-$offset,$offset)))
            {
                Config::Manager::Report->report(@ERROR,
                    "Can't write to file '$target': $!");
                unless (close(SOURCE))
                {
                    Config::Manager::Report->report(@WARN,
                        "Can't close file '$source': $!");
                }
                unless (close(TARGET))
                {
                    Config::Manager::Report->report(@WARN,
                        "Can't close file '$target': $!");
                }
                return undef;
            }
        }
    }
    unless (close(TARGET))
    {
        Config::Manager::Report->report(@ERROR,
            "Can't close file '$target': $!");
        unless (close(SOURCE))
        {
            Config::Manager::Report->report(@WARN,
                "Can't close file '$source': $!");
        }
        return undef;
    }
    unless (close(SOURCE))
    {
        Config::Manager::Report->report(@WARN,
            "Can't close file '$source': $!");
    }
    return 1;
}

sub ConvertFileWithCallback
{
    my($target,$source,$callback) = @_;
    my($line);
    local($/) = "\n";
    local($.);
    local($!);

    unless (defined $callback && ref($callback) && ref($callback) eq 'CODE')
    {
        Config::Manager::Report->report(@FATAL,
            "Parameter '$callback' is not a valid CODE reference!");
        return undef;
    }
    unless (-f $source)
    {
        Config::Manager::Report->report(@ERROR,
            "File '$source' does not exist!");
        return undef;
    }
    unless (open(SOURCE, "<$source"))
    {
        Config::Manager::Report->report(@ERROR,
            "Can't read file '$source': $!");
        return undef;
    }
    unless (open(TARGET, ">$target"))
    {
        Config::Manager::Report->report(@ERROR,
            "Can't write file '$target': $!");
        unless (close(SOURCE))
        {
            Config::Manager::Report->report(@WARN,
                "Can't close file '$source': $!");
        }
        return undef;
    }
    while (defined ($line = <SOURCE>))
    {
        if (defined ($line = &{$callback}($line,$.))) { print TARGET $line; }
    }
    unless (close(TARGET))
    {
        Config::Manager::Report->report(@ERROR,
            "Can't close file '$target': $!");
        unless (close(SOURCE))
        {
            Config::Manager::Report->report(@WARN,
                "Can't close file '$source': $!");
        }
        return undef;
    }
    unless (close(SOURCE))
    {
        Config::Manager::Report->report(@WARN,
            "Can't close file '$source': $!");
    }
    return 1;
}

sub SerializeSimple
{
    my($varname,$object) = @_;
    my($result) = [];

    push( @{$result}, "\$$varname =" );
    &SerializeStruct($object,0,1,$result);
    ${$result}[$#{$result}] .= ";";
    foreach $object (@{$result}) { $object .= "\n"; }
    return $result;
}

sub SerializeStruct
{
    my($object,$indent,$append,$result) = @_;
    my($ref,$fill,$index,$more,$max,$key,$len,$scalar);

    $ref = '';
    $fill = ' ' x $indent;
    while ((ref($object) eq 'REF') || (ref($object) eq 'SCALAR'))
    {
        $ref .= "\\";
        $object = ${$object};
    }
    if (ref($object) eq 'ARRAY')
    {
        if (($max = @{$object}) == 0)
        {
            if ($append) { ${$result}[$#{$result}] .= " ${ref}\[\]"; }
            else         { push( @{$result}, "${fill}${ref}\[\]" ); }
        }
        else
        {
            push( @{$result}, "${fill}${ref}\[" );
            $more = 0;
            $index = 0;
            while ($index < $max)
            {
                ${$result}[$#{$result}] .= "," if ($more);
                &SerializeStruct(${$object}[$index++],$indent+4,0,$result);
                $more = 1;
            }
            push( @{$result}, "${fill}\]" );
        }
    }
    elsif (ref($object) eq 'HASH')
    {
        if (keys(%{$object}) == 0)
        {
            if ($append) { ${$result}[$#{$result}] .= " ${ref}\{\}"; }
            else         { push( @{$result}, "${fill}${ref}\{\}" ); }
        }
        else
        {
            $max = 0;
            foreach $key (keys(%{$object}))
            {
                $len = length($key);
                $max = $len if ($len > $max);
            }
            push( @{$result}, "${fill}${ref}\{" );
            $more = 0;
            foreach $key (sort keys(%{$object}))
            {
                ${$result}[$#{$result}] .= "," if ($more);
                $len = length($key);
                push( @{$result}, "${fill}    '$key'" . ' ' x ($max-$len) . " =>" );
                &SerializeStruct(${$object}{$key},$indent+4,1,$result);
                $more = 1;
            }
            push( @{$result}, "${fill}\}" );
        }
    }
    else
    {
        if (defined $object)
        {
            $scalar = "$object";
            unless ($scalar =~ /^-?(?:[1-9]\d*|0)(?:\.\d+)?$/)
            {
                $scalar =~ s!\\!\\\\!g;
                $scalar =~ s!\$!\\\$!g;
                $scalar =~ s!\n!\\n!g;
                $scalar =~ s!\t!\\t!g;
                $scalar =~ s!"!\\"!g;
                $scalar =~ s!@!\\@!g;
                $scalar =~ s!([\x00-\x1F\x7F-\xFF])!sprintf("\\x%.02X",ord($1))!eg;
                $scalar = "\"$scalar\"";
            }
        }
        else { $scalar = "undef"; }
        if ($append) { ${$result}[$#{$result}] .= " ${ref}$scalar"; }
        else         { push( @{$result}, "${fill}${ref}$scalar" ); }
    }
}

sub Semaphore_Passeer
{
    my($semaphore) = @_; # this is a filename!
    my($wait,$pid);
    local($!);

    $wait = 1;
    # Wait for semaphore:
    WAIT:
    while ($wait)
    {
        # Wait for semaphore to be released (if set):
        while (-f $semaphore) { sleep(1); }
        # When semaphore is gone, create own one:
        unless (open(SEMAPHORE, ">$semaphore"))
        {
            Config::Manager::Report->report(@ERROR,
                "Can't write semaphore '$semaphore': $!");
            unless (unlink($semaphore))
            {
                Config::Manager::Report->report(@WARN,
                    "Could not unlink semaphore '$semaphore': $!");
            }
            next WAIT;
        }
        print SEMAPHORE "$$\n";
        close(SEMAPHORE);
        # Check wether semaphore is our's or was created
        # in the meantime by a different process:
        unless (open(SEMAPHORE, "<$semaphore"))
        {
            Config::Manager::Report->report(@ERROR,
                "Can't read semaphore '$semaphore': $!");
            unless (unlink($semaphore))
            {
                Config::Manager::Report->report(@ERROR,
                    "Could not unlink semaphore '$semaphore': $!");
            }
            next WAIT;
        }
        $pid = <SEMAPHORE>;
        close(SEMAPHORE);
        $pid =~ s!^\s+!!;
        $pid =~ s!\s+$!!;
        # Loop if semaphore isn't our's:
        $wait = ($pid != $$);
        Config::Manager::Report->report(@WARN,
            "Waiting for process '$pid' to release semaphore '$semaphore'...")
        if ($wait);
    }
}

sub Semaphore_Verlaat
{
    my($semaphore) = @_;
    local($!);

    # Release semaphore:
    unless (unlink($semaphore))
    {
        Config::Manager::Report->report(@ERROR,
            "Could not unlink semaphore '$semaphore': $!");
        return undef;
    }
    return 1;
}

sub GetNextTicket
{
    my($lock,$file,$count_min,$count_max) = @_;
    my($ok,$error,$counter);
    local($!);
    local($@);

    $ok = 0;
    $file = Normalize($file);
    $lock = Normalize($lock) if ($lock);
    my $FH_FILE = gensym();
    unless (sysopen($FH_FILE, $file, O_RDWR|O_CREAT))
    {
        Config::Manager::Report->report(@ERROR,
            "Can't open ticket file '$file': $!");
        return undef;
    }
    eval
    {
        $ok = flock($FH_FILE, LOCK_EX);
    };
    if ($@)
    {
        if ($@ =~ /\bunimplemented\b/)
        {
            &Semaphore_Passeer($lock) if ($lock);
            $ok = 1;
        }
        else
        {
            $error = $@;
            $error =~ s!\s+! !g;
            $error =~ s!\(.*$!!;
            $error =~ s!\s+at\s.*$!!;
            $error =~ s!\s+$!!;
            Config::Manager::Report->report(@ERROR,
                "Can't flock ticket file '$file': $error");
            close($FH_FILE);
            return undef;
        }
    }
    else
    {
        if ($ok)
        {
            $lock = '';
        }
        else
        {
            Config::Manager::Report->report(@ERROR,
                "Can't flock ticket file '$file': $!");
            close($FH_FILE);
            return undef;
        }
    }
    unless (seek($FH_FILE, 0, 0))
    {
        Config::Manager::Report->report(@ERROR,
            "Can't seek ticket file '$file': $!");
        close($FH_FILE);
        &Semaphore_Verlaat($lock) if ($lock);
        return undef;
    }
    if (defined ($counter = <$FH_FILE>))
    {
        $counter =~ s!^\s+!!;
        $counter =~ s!\s+$!!;
        if ($counter =~ /^[0-9a-zA-Z]+$/)
        {
            $counter = $count_min if (($counter eq $count_max) || (++$counter gt $count_max));
        }
        else
        {
            $counter = $count_min;
            Config::Manager::Report->report(@WARN,
                "No valid ticket number found in file '$file'!",
                "Resetting the counter to value '$counter'.");
        }
    }
    else
    {
        $counter = $count_min;
        Config::Manager::Report->report(@WARN,
            "No ticket number found in file '$file'!",
            "Setting the counter to value '$counter'.");
    }
    unless (truncate($FH_FILE, 0))
    {
        Config::Manager::Report->report(@ERROR,
            "Can't truncate ticket file '$file': $!");
        close($FH_FILE);
        &Semaphore_Verlaat($lock) if ($lock);
        return undef;
    }
    unless (seek($FH_FILE, 0, 0))
    {
        Config::Manager::Report->report(@ERROR,
            "Can't seek ticket file '$file': $!");
        close($FH_FILE);
        &Semaphore_Verlaat($lock) if ($lock);
        return undef;
    }
    unless (print($FH_FILE "$counter\n"))
    {
        Config::Manager::Report->report(@ERROR,
            "Can't print ticket file '$file': $!");
        close($FH_FILE);
        &Semaphore_Verlaat($lock) if ($lock);
        return undef;
    }
    unless (close($FH_FILE))
    {
        Config::Manager::Report->report(@ERROR,
            "Can't close ticket file '$file': $!");
        &Semaphore_Verlaat($lock) if ($lock);
        return undef;
    }
    &Semaphore_Verlaat($lock) if ($lock);
    return $counter;
}

1;

__END__