Subversion Repositories DevTools

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1042 dpurdie 1
#! /usr/bin/perl
2
########################################################################
3
# Copyright (C) Vix Technology, All rights reserved
4
#
5
# Module name   : pkg_mon.pl
6
# Module type   :
7
# Compiler(s)   : Perl
8
# Environment(s):
9
#
10
# Description   : Dpkg_archive monitor tools
11
#                 Designed to be run periodically from cron
12
#
13
#                 Operations
14
#                   Maintans a list of files in the archive
15
#                       Allows quick greping for files
16
#
17
#......................................................................#
18
 
19
require 5.008_002;
20
use strict;
21
use warnings;
22
 
23
use Pod::Usage;
24
use Getopt::Long;
25
use File::Find;
26
use File::Path;
27
use POSIX qw(strftime);
28
use Data::Dumper;
29
 
30
 
31
#
32
#   Definitions
33
#
34
our $dpkg       = "$ENV{HOME}/dpkg_archive";    # Root of the archive
35
our $list       = 'dpkg_archive_list';          # Base name for lists
36
our $pkg        = 'dpkg_archive_pkg';           # Base name for package list
37
our $keepDays   = 100;                          # Keep for xxx days
38
our $metaDir    = '.dpkg_archive';              # Name of meta directory
39
our $logs       = 'pkg_lists';                  # Subdir to store history of archive
40
our $metadir    = "$dpkg/$metaDir/$logs";       # Store package lists
41
 
42
#
43
#   Globals
44
#
45
our $dirLen     = 0;
46
our $pkgList;
47
our $pkgListLast;
48
our $brokenLinks;
49
 
50
 
51
#-------------------------------------------------------------------------------
52
# Function        : Mainline Entry
53
#
54
# Description     : Designed to be used with CRON and CRON to email
55
#                   admin on errors
56
#
57
# Inputs          : None
58
#
59
# Returns         : None Zero on error
60
#
61
 
62
#
63
#   Must have an archive
64
#
65
if ( ! -d $dpkg  )
66
{
67
    die ("Home directory MUST have link to dpkg_archive");
68
}
69
 
70
#
71
#   Create the meta data directory
72
#   Ensure its writable by owner and readable by all
73
#
74
if ( ! -d $metadir )
75
{
76
    mkpath ($metadir, 0, 0755);
77
    die ("Can't create metadata directory") unless ( -d $metadir );
78
}
79
chmod 0755, $metadir;
80
 
81
#
82
#   Create new file
83
#
84
my $newfile = "$metadir/${list}.NEW";
85
our $fh;
86
unlink $newfile;
87
open ( $fh ,'>', $newfile) or die ("Cannot open file: $newfile. $!");
88
 
89
my $newpkg = "$metadir/${pkg}.NEW";
90
our $ph;
91
unlink $newpkg;
92
open ( $ph ,'>', $newpkg) or die ("Cannot open file: $newpkg $!");
93
 
94
 
95
#   CD to the package archive - the dpkg_archive in the user homedir may be a
96
#   symlink and find won't follow the first.
97
#
98
chdir $dpkg || die ("Cannot cd to $dpkg: $!");
99
 
100
 
101
#
102
#   Walk the package lists
103
#   Done so that we can collect package data and perform specific tests
104
#
105
opendir(DIR, $dpkg) || die "Can't opendir $dpkg: $!";
106
my @dlist = readdir(DIR);
107
closedir DIR;
108
$dirLen = length $dpkg;
109
 
110
scan:
111
foreach my $pname ( sort @dlist )
112
{
113
    next if ( $pname eq '.' );
114
    next if ( $pname eq '..' );
115
    next if ( $pname eq $metaDir);      # Skip Metadata directory
116
 
117
    my $dir = $dpkg . '/'. $pname;
118
    next unless ( -d $dir );
119
 
120
    opendir(DIR, $dir )|| die "Can't opendir $dir: $!";
121
    my @vlist = readdir(DIR);
122
    closedir DIR;
123
 
124
    foreach my $vname ( sort @vlist )
125
    {
126
        next if ( $vname eq '.' );
127
        next if ( $vname eq '..' );
128
        next if ( $vname =~ m~\.TMPDIR$~ );
129
 
130
 
131
        my $vdir = $dir . '/' . $vname;
132
        if ( -d $vdir  )
133
        {
134
            print $ph "$pname/$vname\n";
135
            $pkgList->{$pname}{$vname} = 2;
136
        }
137
 
138
        #
139
        #   Create a list of files in the archive
140
        #   Be careful of symlinks
141
        #
142
        find ( {wanted => \&process_file, follow_fast => 0, no_chdir => 1}, $vdir );
143
 
144
    }
145
}
146
 
147
#
148
#   Close files and rename them
149
#   Maintain a link to the 'current' one
150
#
151
close $fh;
152
nameFile ( $newfile, $list );
153
 
154
close $ph;
155
my $last_pkglist = nameFile ( $newpkg, $pkg );
156
#print "$last_pkglist\n";
157
 
158
#
159
#   Read in the last generated package list
160
#   Update the $pkgList structure
161
#       Data will be:
162
#           1 - Deleted package
163
#           2 - Added package
164
#           3 - Still in place
165
#
166
if ( $last_pkglist )
167
{
168
    open ($fh, '<', "$dpkg/$metaDir/$last_pkglist" ) || die ("Can't open $last_pkglist. $!");
169
    while ( <$fh> )
170
    {
171
        chomp;
172
        my ($pname,$pver) = split( '/', $_);
173
        $pkgList->{$pname}{$pver}++;
174
    }
175
}
176
close $fh;
177
#DebugDumpData('$pkgList', $pkgList );
178
 
179
#
180
#   Determine new package and deleted packages
181
#
182
my $added;
183
my $deleted;
184
 
185
while ( (my ($pname, $pvers)) = each %{$pkgList} ) {
186
    while ( (my ($pver, $pdata) ) = each %{$pvers} ) {
187
        next unless ( $pdata );
188
        next if ( $pdata == 3 );
189
        if ( $pdata == 1 ) {
190
            $deleted->{$pname}{$pver} = 1;
191
        }  else {
192
            $added->{$pname}{$pver} = 1;
193
        }
194
    }
195
}
196
#DebugDumpData('Added', $added );
197
#DebugDumpData('Deleted', $deleted );
198
 
199
 
200
#
201
#   Delete old instances of the package list
202
#   Only retain them them for so long - 100 days
203
#
204
opendir($fh, $metadir) || die "can't opendir $metadir: $!";
205
my @flist = readdir($fh);
206
closedir $fh;
207
 
208
foreach my $fname ( @flist )
209
{
210
    next if ( $fname eq '.' );
211
    next if ( $fname eq '..' );
212
    my $fname = "$metadir/$fname";
213
    next unless ( -M $fname > $keepDays );
214
    unlink $fname;
215
}
216
 
217
#-------------------------------------------------------------------------------
218
# Function        : process_file
219
#
220
# Description     : File::find callback function
221
#                   Process files
222
#
223
# Inputs          : None
224
#                   $File::Find::dir    is the current directory name,
225
#                   $_                  is the current filename within that directory
226
#                   $File::Find::name   is the complete pathname to the file.
227
#
228
# Returns         : Nothing
229
#
230
sub process_file
231
{
232
    my $name = $File::Find::name;
233
    $name = substr ($name, 1+ $dirLen);         # Remove Root
234
#    return unless ( $name =~ m~/.+/~ );         # Skip root level dirs
235
    my $ch = ( -d ) ? '/' : '';                 # Append / to dirs
236
    push @{$brokenLinks}, $name unless ( -e );
237
    print $fh "$name$ch\n";
238
 
239
#print "$name$ch\n";
240
}
241
 
242
 
243
#-------------------------------------------------------------------------------
244
# Function        : nameFile
245
#
246
# Description     : Rename a file and create a link to the current instance
247
#
248
# Inputs          : current_name            - Current name of the file
249
#                   base                    - Base of new name 
250
#
251
# Returns         : Name of the orginal link file
252
#
253
sub nameFile
254
{
255
    my ($newfile, $base) = @_;
256
    my $rv;
257
 
258
    my $timestr = strftime "%Y-%m-%d", localtime();
259
    my $final_name = "${base}.$timestr.txt";
260
    my $final_file = "$metadir/$final_name";
261
    my $link_filename = "${base}.txt";
262
    my $link_file = "$dpkg/$metaDir/$link_filename";
263
 
264
    $rv = readlink($link_file)
265
        if ( -l $link_file );
266
 
267
 
268
    rename $newfile, $final_file;
269
    unlink $link_file;
270
    symlink "$logs" . '/'. $final_name, $link_file;
271
 
272
    return $rv;
273
}
274
 
275
#-------------------------------------------------------------------------------
276
# Function        : DebugDumpData
277
#
278
# Description     : Dump a data structure
279
#
280
# Inputs          : $name           - A name to give the structure
281
#                   @refp           - An array of references
282
#
283
# Returns         :
284
#
285
sub DebugDumpData
286
{
287
    my ($name, @refp) = @_;
288
 
289
    my $ii = 0;
290
    foreach  ( @refp )
291
    {
292
        print Data::Dumper->Dump ( [$_], ["*[Arg:$ii] $name" ]);
293
        $ii++
294
    }
295
}
296