2 # $Id: errorlib.in,v 1.33 2003/08/06 18:45:41 cjwatson Exp $
6 sub F_SETLK { 6; } sub F_WRLCK{ 1; }
7 $flockstruct= 'sslll'; # And there ought to be something for this too.
10 return "" if ( $_[ 0 ] < 0 );
11 return sprintf "%02d", $_[ 0 ] % 100;
14 sub unlockreadbugmerge {
16 &unfilelock if $rv >= 2;
17 &unfilelock if $rv >= 1;
20 sub lockreadbugmerge {
21 local ($lref, $location) = @_;
23 if (!($data = &lockreadbug($lref, $location))) { return ( 0, undef ); }
24 if (!length($data{mergedwith})) { return ( 1, $data ); }
26 &filelock('lock/merge');
27 if (!&lockreadbug($lref, $location)) { &unfilelock; return ( 0, undef ); }
32 my ( $bugnum, $ext ) = @_;
33 my $archdir = sprintf "%02d", $bugnum % 100;
34 return 'archive' if ( -r "$gSpoolDir/archive/$archdir/$bugnum.$ext" );
35 return 'db-h' if ( -r "$gSpoolDir/db-h/$archdir/$bugnum.$ext" );
36 return 'db' if ( -r "$gSpoolDir/db/$bugnum.$ext" );
42 if ($location eq 'archive') {
43 return "$gSpoolDir/archive";
44 } elsif ($location eq 'db') {
45 return "$gSpoolDir/db";
47 return "$gSpoolDir/db-h";
52 my ($bugnum, $ext, $location) = @_;
54 unless (defined $location) {
55 $location = getbuglocation($bugnum, $ext);
56 # Default to non-archived bugs only for now; CGI scripts want
57 # archived bugs but most of the backend scripts don't. For now,
58 # anything that is prepared to accept archived bugs should call
59 # getbuglocation() directly first.
60 return undef if defined $location and
61 ($location ne 'db' and $location ne 'db-h');
63 my $dir = getlocationpath($location);
64 return undef unless $dir;
65 if ($location eq 'db') {
66 return "$dir/$bugnum.$ext";
68 my $hash = get_hashname($bugnum);
69 return "$dir/$hash/$bugnum.$ext";
74 local ($lref, $location) = @_;
75 my $status = getbugcomponent($lref, 'status', $location);
76 return undef unless defined $status;
77 if (!open(S,$status)) { return undef; }
79 chop($data{originator}= <S>);
80 chop($data{date}= <S>);
81 chop($data{subject}= <S>);
82 chop($data{msgid}= <S>);
83 chop($data{package}= <S>);
84 chop($data{keywords}= <S>);
85 chop($data{done}= <S>);
86 chop($data{forwarded}= <S>);
87 chop($data{mergedwith}= <S>);
88 chop($data{severity}= <S>);
89 chop($data{versions}= <S>);
90 chop($data{fixed_versions}= <S>);
92 $data{severity} = 'normal' if $data{severity} eq '';
97 local ($lref, $location) = @_;
98 &filelock("lock/$lref");
99 my $data = readbug($lref, $location);
100 &unfilelock unless defined $data;
107 "$data->{originator}\n".
109 "$data->{subject}\n".
111 "$data->{package}\n".
112 "$data->{keywords}\n".
114 "$data->{forwarded}\n".
115 "$data->{mergedwith}\n".
116 "$data->{severity}\n".
117 "$data->{versions}\n".
118 "$data->{fixed_versions}\n";
123 local ($ref, $data, $location) = @_;
125 my $status = getbugcomponent($ref, 'status', $location);
126 &quit("can't find location for $ref") unless defined $status;
127 open(S,"> $status.new") || &quit("opening $status.new: $!");
128 print(S makestatus($data)) || &quit("writing $status.new: $!");
129 close(S) || &quit("closing $status.new: $!");
135 rename("$status.new",$status) || &quit("installing new $status: $!");
136 &bughook($change,$ref,$data);
145 # NB - NOT COMPATIBLE WITH `with-lock'
146 local ($lockfile,$flockpushno,$evalstring,$count,$errors,@s1,@s2) = @_;
147 $flockpushno= $#filelocks+1;
148 $count= 10; $errors= '';
151 open(FLOCK${flockpushno},\"> \$lockfile\") || die \"open: \$!\";
152 \$flockwant= pack(\$flockstruct,&F_WRLCK,0,0,1,0);".
154 fcntl(FLOCK$flockpushno,&F_SETLK,\$flockwant) || die \"setlk: \$!\";" : "
155 \$z= syscall(&SYS_fcntl,fileno(FLOCK$flockpushno),&F_SETLK,\$flockwant) < 0
156 && die \"syscall fcntl setlk: \$!\";") ."
157 (\@s1= lstat(\$lockfile)) || die \"lstat: \$!\";
158 (\@s2= stat(FLOCK$flockpushno)) || die \"fstat: \$!\";
159 join(',',\@s1) eq join(',',\@s2) || die \"file switched\";
162 last if eval $evalstring;
164 eval "close(FLOCK$flockpushno);";
167 &quit("failed to get lock on file $lockfile: $errors // $evalstring");
171 push(@cleanups,'unfilelock');
172 push(@filelocks,$lockfile);
176 if (@filelocks == 0) {
177 warn "unfilelock called with no active filelocks!\n";
180 local ($lockfile) = pop(@filelocks);
182 eval 'close(FLOCK'.($#filelocks+1).');' || warn "failed to close lock file $lockfile: $!";
183 unlink($lockfile) || warn "failed to remove lock file $lockfile: $!";
187 print DEBUG "quitting >$_[0]<\n";
189 while ($u= $cleanups[$#cleanups]) { &$u; }
193 %saniarray= ('<','lt', '>','gt', '&','amp', '"','quot');
198 while ($in =~ m/[<>&"]/) {
199 $out.= $`. '&'. $saniarray{$&}. ';';
206 sub update_realtime {
207 my ($file, $bug, $new) = @_;
209 # update realtime index.db
211 open(IDXDB, "<$file") or die "Couldn't open $file";
212 open(IDXNEW, ">$file.new");
216 while($line = <IDXDB>) {
217 @line = split /\s/, $line;
218 last if ($line[1] >= $bug);
223 if ($new eq "NOCHANGE") {
224 print IDXNEW $line if ($line ne "" && $line[1] == $ref);
225 } elsif ($new eq "REMOVE") {
230 if ($line ne "" && $line[1] > $bug) {
235 print IDXNEW while(<IDXDB>);
240 rename("$file.new", $file);
245 sub bughook_archive {
247 &filelock("debbugs.trace.lock");
248 &appendfile("debbugs.trace","archive $ref\n");
249 my $line = update_realtime(
250 "$gSpoolDir/index.db.realtime",
253 update_realtime("$gSpoolDir/index.archive.realtime",
259 my ( $type, $ref, $data ) = @_;
260 &filelock("debbugs.trace.lock");
262 &appendfile("debbugs.trace","$type $ref\n",makestatus($data));
264 my $whendone = "open";
265 my $severity = $gDefaultSeverity;
266 (my $pkglist = $data->{package}) =~ s/[,\s]+/,/g;
269 $whendone = "forwarded" if length $data->{forwarded};
270 $whendone = "done" if length $data->{done};
271 $severity = $data->{severity} if length $data->{severity};
273 my $k = sprintf "%s %d %d %s [%s] %s %s\n",
274 $pkglist, $ref, $data->{date}, $whendone,
275 $data->{originator}, $severity, $data->{keywords};
277 update_realtime("$gSpoolDir/index.db.realtime", $ref, $k);
284 if (!open(AP,">>$file")) {
285 print DEBUG "failed open log<\n";
286 print DEBUG "failed open log err $!<\n";
287 &quit("opening $file (appendfile): $!");
289 print(AP @_) || &quit("writing $file (appendfile): $!");
290 close(AP) || &quit("closing $file (appendfile): $!");
295 my $type = $entity->effective_type;
296 if ($type eq 'text/plain' or
297 ($type =~ m#text/# and $type ne 'text/html') or
298 $type eq 'application/pgp') {
299 return $entity->bodyhandle;
300 } elsif ($type eq 'multipart/alternative') {
301 # RFC 2046 says we should use the last part we recognize.
302 for my $part (reverse $entity->parts) {
303 my $ret = getmailbody($part);
307 # For other multipart types, we just pretend they're
308 # multipart/mixed and run through in order.
309 for my $part ($entity->parts) {
310 my $ret = getmailbody($part);
319 map { $_->address() }
320 map { Mail::Address->parse($_) } @_;
325 map { s/^([\01-\07\030])/\030$1/gm } @log;
330 @severities= grep { not exists $gObsoleteSeverities{$_} } @gSeverityList;
331 @showseverities= @severities;
332 grep ($_= $_ eq '' ? $gDefaultSeverity : $_, @showseverities);
333 @strongseverities= @gStrongSeverities;
334 %displayshowseverities= %gSeverityDisplay;