2 package Debbugs::Common;
6 Debbugs::Common -- Common routines for all of Debbugs
10 use Debbugs::Common qw(:url :html);
15 This module is a replacement for the general parts of errorlib.pl.
16 subroutines in errorlib.pl will be gradually phased out and replaced
17 with equivalent (or better) functionality here.
25 use vars qw($VERSION $DEBUG %EXPORT_TAGS @EXPORT_OK @EXPORT);
26 use base qw(Exporter);
30 $DEBUG = 0 unless defined $DEBUG;
33 %EXPORT_TAGS = (util => [qw(getbugcomponent getbuglocation getlocationpath get_hashname),
34 qw(appendfile buglog),
37 lock => [qw(filelock unfilelock)],
40 Exporter::export_ok_tags(qw(lock quit util));
41 $EXPORT_TAGS{all} = [@EXPORT_OK];
44 #use Debbugs::Config qw(:globals);
45 use Debbugs::Config qw(:config);
47 use Debbugs::MIME qw(decode_rfc1522);
53 The following functions are exported by the C<:util> tag
55 =head2 getbugcomponent
57 my $file = getbugcomponent($bug_number,$extension,$location)
59 Returns the path to the bug file in location C<$location>, bug number
60 C<$bugnumber> and extension C<$extension>
65 my ($bugnum, $ext, $location) = @_;
67 if (not defined $location) {
68 $location = getbuglocation($bugnum, $ext);
69 # Default to non-archived bugs only for now; CGI scripts want
70 # archived bugs but most of the backend scripts don't. For now,
71 # anything that is prepared to accept archived bugs should call
72 # getbuglocation() directly first.
73 return undef if defined $location and
74 ($location ne 'db' and $location ne 'db-h');
76 return undef if not defined $location;
77 my $dir = getlocationpath($location);
78 return undef if not defined $dir;
79 if ($location eq 'db') {
80 return "$dir/$bugnum.$ext";
82 my $hash = get_hashname($bugnum);
83 return "$dir/$hash/$bugnum.$ext";
89 getbuglocation($bug_number,$extension)
91 Returns the the location in which a particular bug exists; valid
92 locations returned currently are archive, db-h, or db. If the bug does
93 not exist, returns undef.
98 my ($bugnum, $ext) = @_;
99 my $archdir = get_hashname($bugnum);
100 return 'archive' if -r getlocationpath('archive')."/$archdir/$bugnum.$ext";
101 return 'db-h' if -r getlocationpath('db-h')."/$archdir/$bugnum.$ext";
102 return 'db' if -r getlocationpath('db')."/$bugnum.$ext";
107 =head2 getlocationpath
109 getlocationpath($location)
111 Returns the path to a specific location
115 sub getlocationpath {
117 if (defined $location and $location eq 'archive') {
118 return "$config{spool_dir}/archive";
119 } elsif (defined $location and $location eq 'db') {
120 return "$config{spool_dir}/db";
122 return "$config{spool_dir}/db-h";
131 Returns the hash of the bug which is the location within the archive
136 return "" if ( $_[ 0 ] < 0 );
137 return sprintf "%02d", $_[ 0 ] % 100;
144 Returns the path to the logfile corresponding to the bug.
150 my $location = getbuglocation($bugnum, 'log');
151 return getbugcomponent($bugnum, 'log', $location) if ($location);
152 $location = getbuglocation($bugnum, 'log.gz');
153 return getbugcomponent($bugnum, 'log.gz', $location);
159 appendfile($file,'data','to','append');
161 Opens a file for appending and writes data to it.
167 if (!open(AP,">>$file")) {
168 print DEBUG "failed open log<\n";
169 print DEBUG "failed open log err $!<\n";
170 &quit("opening $file (appendfile): $!");
172 print(AP @_) || &quit("writing $file (appendfile): $!");
173 close(AP) || &quit("closing $file (appendfile): $!");
178 These functions are exported with the :lock tag
184 FLOCKs the passed file. Use unfilelock to unlock it.
192 # NB - NOT COMPATIBLE WITH `with-lock'
194 my ($count,$errors) = @_;
195 $count= 10; $errors= '';
198 my $fh = new IO::File $lockfile,'w'
199 or die "Unable to open $lockfile for writing: $!";
200 flock($fh,LOCK_EX|LOCK_NB)
201 or die "Unable to lock $lockfile $!";
208 push @filelocks, {fh => $fh, file => $lockfile};
213 &quit("failed to get lock on $lockfile -- $errors");
217 push(@cleanups,\&unfilelock);
225 Unlocks the file most recently locked.
227 Note that it is not currently possible to unlock a specific file
228 locked with filelock.
233 if (@filelocks == 0) {
234 warn "unfilelock called with no active filelocks!\n";
237 my %fl = %{pop(@filelocks)};
239 flock($fl{fh},LOCK_UN)
240 or warn "Unable to unlock lockfile $fl{file}: $!";
242 or warn "Unable to close lockfile $fl{file}: $!";
244 or warn "Unable to unlink locfile $fl{file}: $!";
251 These functions are exported with the :quit tag.
257 Exits the program by calling die after running some cleanups.
259 This should be replaced with an END handler which runs the cleanups
260 instead. (Or possibly a die handler, if the cleanups are important)
265 print DEBUG "quitting >$_[0]<\n";
267 while ($u= $cleanups[$#cleanups]) { &$u; }