Subversion Repositories DevTools

Rev

Rev 1040 | Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1038 dpurdie 1
package Utils;
2
use File::Basename;
3
use Data::Dumper;
4
 
5
sub trunc ($) {
6
	my $file = shift;
7
	open my $fh, ">$file" or die "Can't write $file: $!\n";
8
	print $fh '';
9
	close $fh;
10
}
11
 
12
sub checkpid ($) {
13
	my $conf = shift;
14
	my $pidfile = $conf->{'pidfile'};
15
	my $logger = $conf->{logger};
16
 
17
	trunc $pidfile unless -f $pidfile;
18
 
19
	open my $fh, $pidfile or $logger->err("Can't read pidfile $pidfile: $!");
20
	my ($pid) = <$fh>;
21
	close $fh;
22
 
23
	if (defined $pid) {
24
		chomp $pid;
25
		$logger->err("Process with pid $pid already running") if 0 < int $pid && kill 0, $pid;
26
	}
27
}
28
 
29
sub writepid ($) {
30
	my $conf = shift;
31
	my $logger = $conf->{logger};
32
	my $pidfile = $conf->{'pidfile'};
33
 
34
	open my $fh, ">$pidfile" or $logger->err("Can't write pidfile: $!");
35
	print $fh "$$\n";
36
	close $fh;
37
}
38
 
39
#-------------------------------------------------------------------------------
40
# Function        : trimstr
41
#
42
# Description     : Trim a string
43
#
44
# Inputs          : Array of strings
45
#
46
# Returns         : Array of trimmed strings
47
#
48
sub trimstr (@) {
49
	my @str = @_;
50
 
51
	for (@str) {
52
		chomp;
53
		s/^[\t\s]+//;
54
		s/[\t\s]+$//;
55
	}
56
 
57
	return @str;
58
}
59
 
60
#-------------------------------------------------------------------------------
61
# Function        : readconf
62
#
63
# Description     : Process config data
64
#
65
# Inputs          : $conffile   - Config file to read
66
#                   $pdata      - Ref to hash of controlling data
67
#                                 hashed by config item and '.ignore'
68
#                                 Values are:
69
#                                   default     - Default value
70
#                                   mandatory   - Must be present
71
#                                   fmt         - Format
72
#                                                   'size'      - convert to block
73
#                                                   'period'    - convert to time
74
#                                                   'dir'       - Directory
75
#                                                   'file'      - File
76
#                                                   'vfile'     - File. Path must exist
77
#                                                   'int'       - integer
78
#                                                   'int_list'  - A list of integers
79
#                                                   'text'      - Random Text
80
#                                                   'bool'      - y/n 1/0
81
#                               .ignore       - Regexp of items to ignore
82
#
83
#
84
#
85
# Returns         : $conf       - Ref to config data
86
#                   $errors     - Ref to an array of error messages
87
#
88
 
89
sub readconf
90
{
91
    my ($conffile, $pdata) = @_;
92
    my @errors;
93
	my $conf;
94
    my $ignored;
95
 
96
    if ( open my $fh, $conffile )
97
    {
98
	    while (<$fh>) {
99
		    next if /^[\t\w]+#/;
100
		    s/#.*//;
101
 
102
		    my ($key, $val) = trimstr split '=', $_, 2;
103
		    next unless defined $val;
104
		    $conf->{$key} = $val;
105
	    }
106
	    close $fh;
107
 
108
        #
109
        #   Validate mandatory entries
110
        #   Insert defaults that are not present
111
        #
112
        while ( (my ($key, $entry)) = each %{$pdata} )
113
        {
114
            if ( exists $entry{mandatory} && $entry{mandatory}  )
115
            {
116
                if ( !exists $conf->{$key} )
117
                {
118
                    push @errors, "Mandatory config not found: $key";
119
                }
120
            }
121
 
122
            if ( exists $entry{default} )
123
            {
124
                if ( !exists $conf->{$key} )
125
                {
126
                    $conf->{$key} = $entry{default};
127
                }
128
            }
129
        }
130
 
131
        #
132
        #   Scan all user items
133
        #
134
        my $ignore_re = $pdata->{'.ignore'} ;
135
        while ( (my ($key, $data)) = each %{$conf} )
136
        {
137
            if ( $ignore_re )
138
            {
139
                #
140
                #   Ignore entry is a hash of entries to ignore
141
                #       Key is RE with a group
142
                #       Value is the name of config item under which the
143
                #       data will be stored. The re group will be used to
144
                #       as the key for the final hash.
145
                #
146
                my $done = 0;
147
                while ( (my ($re, $ename)) = each %{$ignore_re} )
148
                {
149
                    if ( $key =~ m~$re~ )
150
                    {
151
                        $ignored->{$ename}{$1} = $data;
152
                        $done = 1;
153
                    }
154
                }
155
                if ( $done )
156
                {
157
                    delete $conf->{$key};
158
                    next;
159
                }
160
            }
161
 
162
            if ( !exists $pdata->{$key} )
163
            {
164
                push @errors, "Unknown config item: $key";
165
                next;
166
            }
167
 
168
            my $fmt = $pdata->{$key}{'fmt'};
169
            unless ( $fmt )
170
            {
171
                push @errors, "Unconfigured config item: $key";
172
                next;
173
            }
174
 
175
            if ( $fmt eq 'size' ) {
176
                $conf->{$key} = toBytes( $data );
177
            } elsif ( $fmt eq 'period' ) {
178
                $conf->{$key} = timeToSecs( $data );
179
 
180
            } elsif ( $fmt eq 'dir' ) {
181
                if ( ! -d $data ) {
182
                    push @errors, "Directory not found:$key: $data";
183
                }
184
            } elsif ( $fmt eq 'file' ) {
185
                if ( ! -f $data ) {
186
                    push @errors, "File not found:$key: $data";
187
                }
188
            } elsif ( $fmt eq 'vfile' ) {
189
                 my($filename, $pdir, $suffix) = fileparse($data);
190
                if ( ! -d $pdir ) {
191
                    push @errors, "Directory not found:$key: $pdir";
192
                }
193
            } elsif ( $fmt eq 'int' ) {
194
                unless ( $data =~ m~^\d+$~ ) {
195
                    push @errors, "Invalid Number:$key: $data";
196
                }
197
            } elsif ( $fmt eq 'int_list' ) {
198
                unless ( $data =~ m~^((\d+)[, ]*)*$~ ) {
199
                    push @errors, "Invalid Number List:$key: $data";
200
                }
201
            } elsif ( $fmt eq 'bool' ) {
202
                $data = lc $data;
203
                if ( $data eq '1' || $data eq 'y'  || $data eq 'yes') {
204
                    $conf->{$key} = 1;
205
                } elsif ( $data eq '0' || $data eq 'n' || $data eq 'no') {
206
                    $conf->{$key} = 0;
207
                } else {
208
                    push @errors, "Invalid Boolean:$key: $data";
209
                }
210
 
211
            } elsif ( $fmt eq 'text' ) {
212
 
213
            } else {
214
                push @errors, "Unknown config fmt:$key, $fmt";
215
            }
216
        }
217
    }
218
    else
219
    {
220
        push @errors, "Can't read $conffile: $!";
221
    }
222
 
223
    #
224
    #   Merge in ignored entries
225
    #
226
    while ( my ($key, $data ) = each %{$ignored})
227
    {
228
        $conf->{$key} = $data;
229
    }
230
 
231
#DebugDumpData('config', $conf );
232
    return $conf, \@errors;
233
}
234
 
235
#-------------------------------------------------------------------------------
236
# Function        : mtime
237
#
238
# Description     : Return the modification time of a file
239
#
240
# Inputs          : $path
241
#
242
# Returns         : modification time
243
#                   mode
244
#
245
sub mtime
246
{
247
    my ($path) = @_;
248
    my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
249
       $atime,$mtime,$ctime,$blksize,$blocks) = stat($path);
250
    return (($mtime || 0), $mode);
251
}
252
 
253
#-------------------------------------------------------------------------------
254
# Function        : timeToSecs
255
#
256
# Description     : Process a string and convert it to seconds
257
#                   Handle:
258
#                       100     -> 100 seconds
259
#                       100s    -> 100 seconds
260
#                       5m      -> 5 minutes
261
#                       10h     -> 10 hours
262
#                       1d      -> 1 day
263
#                       1d10h   -> 1d and 10 hours
264
#
265
#
266
# Inputs          : String
267
#
268
# Returns         : Seconds
269
#
270
sub timeToSecs
271
{
272
    my ($src) = @_;
273
    my $result = 0;
274
    while ( $src =~ s~(\d+)([smhd])?~~ )
275
    {
276
        my $factor = 1;
277
        my $base = $1;
278
        my $mode = $2 || 's';
279
        if ( $mode eq 'd' ) {
280
            $factor = 24 * 60 * 60;
281
        } elsif ( $mode eq 'h' ) {
282
            $factor = 60 * 60;
283
        } elsif ( $mode eq 'm' ) {
284
            $factor = 60;
285
        }
286
        $result += $base * $factor;
287
    }
288
    return $result;
289
}
290
 
291
#-------------------------------------------------------------------------------
292
# Function        : toBytes
293
#
294
# Description     : Process a string and convert it to a byte count
295
#                   Handle:
296
#                       100     -> 100 bytes
297
#                       10k     -> 10 kilobytes
298
#                       5m      -> 5 Megabytes
299
#                       1g      -> 1 Gigabytes
300
#                       10b     -> 10 Blocks
301
#
302
# Inputs          : String
303
#
304
# Returns         : Byte Count
305
#
306
sub toBytes
307
{
308
    my ($src) = @_;
309
    my $result = 0;
310
    if ( $src =~ m~(\d+)([kmgb]?)~i )
311
    {
312
        my $factor = 1;
313
        my $base = $1;
314
        my $mode = lc($2) || '-';
315
        if ( $mode eq 'g' ) {
316
            $factor = 1024 * 1024 * 1024;
317
        } elsif ( $mode eq 'm' ) {
318
            $factor = 1024 * 1024;
319
        } elsif ( $mode eq 'k' ) {
320
            $factor = * 1024;
321
        } elsif ( $mode eq 'b' ) {
322
            $factor = 1024;
323
        }
324
        $result = $base * $factor;
325
    }
326
    return $result;
327
}
328
 
329
#-------------------------------------------------------------------------------
330
# Function        : DebugDumpData
331
#
332
# Description     : Dump a data structure
333
#
334
# Inputs          : $name           - A name to give the structure
335
#                   @refp           - An array of references
336
#
337
# Returns         :
338
#
339
sub DebugDumpData
340
{
341
    my ($name, @refp) = @_;
342
 
343
    my $ii = 0;
344
    foreach  ( @refp )
345
    {
346
        print Data::Dumper->Dump ( [$_], ["*[Arg:$ii] $name" ]);
347
        $ii++
348
    }
349
}
350
 
351
 
352
1;