# # $Date: 2006/05/03 22:12:57 $ # # Notes and sequencer functions # # Brian Carrier [carrier@sleuthkit.org] # Copyright (c) 2001-2005 by Brian Carrier. All rights reserved # # This file is part of the Autopsy Forensic Browser (Autopsy) # # Autopsy is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # Autopsy 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. # # You should have received a copy of the GNU General Public License # along with Autopsy; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED # WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF # MERCHANTABILITY AND FITNESS FOR ANY PARTICULAR PURPOSE. # IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, # INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES # (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA, OR PROFITS OR # BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, # WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR # OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF # ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package Notes; use POSIX; $Notes::ENTER_FILE = 1; $Notes::ENTER_DATA = 2; $Notes::WRITE_FILE = 3; $Notes::WRITE_DATA = 4; $Notes::WRITE_SEQ_MAN = 5; $Notes::READ_NORM = 6; $Notes::READ_SEQ = 7; sub main { # There is no default for Notes Args::check_view(); Print::print_check_error("Notes option is not enabled") if ($::USE_NOTES == 0); my $view = Args::get_view(); if ($view == $Notes::ENTER_FILE) { return enter_file(); } elsif ($view == $Notes::ENTER_DATA) { return enter_data(); } elsif ($view == $Notes::WRITE_FILE) { return write_file(); } elsif ($view == $Notes::WRITE_DATA) { return write_data(); } elsif ($view == $Notes::WRITE_SEQ_MAN) { return write_seq_man(); } elsif ($view == $Notes::READ_NORM) { return read_norm(); } elsif ($view == $Notes::READ_SEQ) { return read_seq(); } else { Print::print_check_err("Invalid Notes View"); } } sub investig_notes_fname { return "$::host_dir" . "$::LOGDIR/$Args::args{'inv'}.notes"; } sub investig_seq_notes_fname { return "$::host_dir" . "$::LOGDIR/$Args::args{'inv'}.seq.notes"; } # window where user can enter a normal and sequencer note for a file # or meta data structure. sub enter_file { Args::check_vol('vol'); Args::check_meta('meta'); my $vol = Args::get_vol('vol'); my $ftype = $Caseman::vol2ftype{$vol}; my $mnt = $Caseman::vol2mnt{$vol}; my $meta = Args::get_meta('meta'); # A file will have a 'dir' argument and a meta structure will not if (exists $Args::args{'dir'}) { my $fname = "$mnt$Args::args{'dir'}"; Print::print_html_header("Notes for file $fname"); print "
Enter a note for $fname ($meta):" . "

\n"; } else { Print::print_html_header("Notes for $Fs::meta_str{$ftype} $meta"); print "
Enter a note for $Fs::meta_str{$ftype} $meta:" . "

\n"; } print "A note works like a bookmark and allows you to later find this data more easily.

\n"; # Setup the form print "
\n" . "
\n" . "\n" . "\n" . "\n" . "\n" . Args::make_hidden(); print "\n" if (exists $Args::args{'dir'}); # Option to add a normal note print "\n" . " Add a Standard Note
\n"; # Sequencer notes - which requires the MAC times for the files if ("$Caseman::tz" ne "") { $ENV{TZ} = $Caseman::tz; POSIX: tzset(); } my $img = $Caseman::vol2path{$vol}; my $offset = $Caseman::vol2start{$vol}; my $imgtype = $Caseman::vol2itype{$vol}; my $meta_int = $meta; $meta_int = $1 if ($meta_int =~ /^(\d+)-\d+(-\d+)?$/); local *OUT; Exec::exec_pipe(*OUT, "'$::TSKDIR/ils' -f $ftype -e -o $offset -i $imgtype $img $meta_int"); # Get the fourth line my $tmp = Exec::read_pipe_line(*OUT); $tmp = Exec::read_pipe_line(*OUT); $tmp = Exec::read_pipe_line(*OUT); $tmp = Exec::read_pipe_line(*OUT); close(OUT); unless ((defined $tmp) && ($tmp =~ /^$::REG_META\|\w\|\d+\|\d+\|(\d+)\|(\d+)\|(\d+)\|/o)) { Print::print_err("Error parsing 'ils' output
"); } my $mtime = $1; my $atime = $2; my $ctime = $3; $mtime = localtime($mtime); $atime = localtime($atime); $ctime = localtime($ctime); # Print the Times print "

Add a Sequencer Event:

\n" . "A sequencer event will be sorted based on the time so that event reconstruction will be easier

\n" . "" . "  M-Time ($mtime)
\n" . "" . "  A-Time ($atime)
\n" . "" . "  C-Time ($ctime)


\n"; # The OK Button print "
\n
\n"; Print::print_html_footer(); return 0; } # data unit comment sub enter_data { Args::check_vol('vol'); my $vol = Args::get_vol('vol'); my $ftype = $Caseman::vol2ftype{$vol}; my $block = Args::get_block(); my $len = Args::get_len(); Print::print_html_header("Notes for $Fs::addr_unit{$ftype} $block"); print "
Enter a note for $Fs::addr_unit{$ftype} $block

\n" . "A note works like a bookmark and allows you to later find this data more easily.

\n" . "
\n" . "
\n" . "\n" . "\n" . "\n" . "\n" . "\n" . "\n" . Args::make_hidden() . "
\n
\n"; Print::print_html_footer(); return 0; } # Write the note to the note file sub write_data { Args::check_vol('vol'); Args::check_block(); Args::check_len(); Args::check_note(); Print::print_html_header("Write a note"); my $vol = Args::get_vol('vol'); my $ftype = $Caseman::vol2ftype{$vol}; my $img_sh = $Caseman::vol2sname{$vol}; my $block = Args::get_block(); my $len = Args::get_len(); Print::log_host_inv( "$img_sh: Creating note for $Fs::addr_unit{$ftype} $block"); my $notes_file = investig_notes_fname(); open NOTES, ">>$notes_file" or die "Can't open log: $notes_file"; print "Note added to $notes_file:

\n\n"; # Date my $tmp = localtime(); print NOTES "$tmp\n"; print "$tmp
\n"; print NOTES "Volume: $vol $Fs::addr_unit{$ftype}: $block Len: $len\n"; print "Volume: $vol $Fs::addr_unit{$ftype}: $block Len: $len
\n"; # The actual notes and a line at the bottom print NOTES "\n$Args::args{'note'}\n\n" . "-" x 70 . "\n"; print "

$Args::args{'note'}

"; close(NOTES); print "


\n" . "You can view the notes from the Host Manager View

" . "" . "\"View\n"; Print::print_html_footer(); return 0; } sub write_file { Args::check_vol('vol'); Args::check_meta('meta'); Args::check_note(); # Get rid of carriage returns that Netscape adds $Args::args{'note'} =~ tr/\r//d; my $vol = Args::get_vol('vol'); my $mnt = $Caseman::vol2mnt{$vol}; my $ftype = $Caseman::vol2ftype{$vol}; my $img_sh = $Caseman::vol2sname{$vol}; my $meta = Args::get_meta('meta'); my $img = $Caseman::vol2path{$vol}; my $offset = $Caseman::vol2start{$vol}; my $imgtype = $Caseman::vol2itype{$vol}; my $fname = ""; my $type = ""; if (exists $Args::args{'dir'}) { $Args::args{'dir'} .= "/" if ($Args::args{'dir'} eq ""); $fname = "$mnt$Args::args{'dir'}"; if (($Args::args{'dir'} =~ /\/$/) || ($Args::args{'dir'} eq "")) { Print::log_host_inv( "$img_sh: Creating note for directory $fname ($meta)"); $type = "dir"; } else { Print::log_host_inv( "$img_sh: Creating note for file $fname ($meta)"); $type = "file"; } } else { Print::log_host_inv( "$img_sh: Creating note for $Fs::meta_str{$ftype} $meta"); $type = "$Fs::meta_str{$ftype}"; } Print::print_html_header("Writing a note / event"); # Get the times for the meta # Set the timezone to the host zone if ("$Caseman::tz" ne "") { $ENV{TZ} = "$Caseman::tz"; POSIX::tzset(); } my $meta_int = $meta; $meta_int = $1 if ($meta_int =~ /^(\d+)-\d+(-\d+)?$/); local *OUT; Exec::exec_pipe(*OUT, "'$::TSKDIR/ils' -f $ftype -e -o $offset -i $imgtype $img $meta_int"); # Skip to the fourth line my $tmp = Exec::read_pipe_line(*OUT); $tmp = Exec::read_pipe_line(*OUT); $tmp = Exec::read_pipe_line(*OUT); $tmp = Exec::read_pipe_line(*OUT); unless ((defined $tmp) && ($tmp =~ /^$::REG_META\|\w\|\d+\|\d+\|(\d+)\|(\d+)\|(\d+)\|/o)) { Print::print_err("Error parsing 'ils' output
"); } my $mtime = $1; my $atime = $2; my $ctime = $3; close(OUT); # Create a "normal" note if ((exists $Args::args{'norm_note'}) && ($Args::args{'norm_note'} == 1)) { my $notes_file = investig_notes_fname(); open NOTES, ">>$notes_file" or die "Can't open log: $notes_file"; print "Note added to $notes_file:

\n\n"; # Date my $tmp = localtime(); print NOTES "$tmp\n"; print "$tmp\n"; # We have a file name if ($fname ne "") { if ($type eq 'dir') { print NOTES "Directory: $fname\n"; print "Directory: $fname
\n"; } else { print NOTES "File: $fname\n"; print "File: $fname
\n"; } } if ($meta ne "") { print NOTES "Volume: $vol Meta: $meta\n"; print "Volume: $vol Meta: $meta
\n"; } print NOTES "M-time: " . localtime($mtime) . "\n"; print "M-time: " . localtime($mtime) . "
\n"; print NOTES "A-time: " . localtime($atime) . "\n"; print "A-time: " . localtime($atime) . "
\n"; print NOTES "C-time: " . localtime($ctime) . "\n"; print "C-time: " . localtime($ctime) . "
\n"; # The actual notes and a line at the bottom print NOTES "\n$Args::args{'note'}\n\n" . "-" x 70 . "\n"; print "

$Args::args{'note'}

"; close(NOTES); } # Create a sequencer event - if there are any unless (((exists $Args::args{'mtime'}) && ($Args::args{'mtime'} == 1)) || ((exists $Args::args{'atime'}) && ($Args::args{'atime'} == 1)) || ((exists $Args::args{'ctime'}) && ($Args::args{'ctime'} == 1))) { print "


\n" . "You can view the notes from the Host Manager View

" . "" . "\"View\n"; Print::print_html_footer(); return 0; } # Get rid of the carriage returns $Args::args{'note'} =~ s/\n/
/gs; my $notes_file = investig_seq_notes_fname(); open NOTES, ">>$notes_file" or die "Can't open log: $notes_file"; if ((exists $Args::args{'mtime'}) && ($Args::args{'mtime'} == 1)) { my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime($mtime); $year += 1900; $mon += 1; $mday = "0$mday" if ($mday < 10); $hour = "0$hour" if ($hour < 10); $min = "0$min" if ($min < 10); $sec = "0$sec" if ($sec < 10); print NOTES "'$year','$mon','$mday','$hour','$min','$sec'," . "'$Args::args{'host'}','$vol','$fname','$meta',''," . "'$type','[M-Time]$Args::args{'note'}'\n"; Print::log_host_inv( "$img_sh: M-Time note added for meta $Args::args{'meta'}"); print "M-Time sequence event added
\n"; } if ((exists $Args::args{'atime'}) && ($Args::args{'atime'} == 1)) { my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime($atime); $year += 1900; $mon += 1; $mday = "0$mday" if ($mday < 10); $hour = "0$hour" if ($hour < 10); $min = "0$min" if ($min < 10); $sec = "0$sec" if ($sec < 10); print NOTES "'$year','$mon','$mday','$hour','$min','$sec'," . "'$Args::args{'host'}','$vol','$fname','$meta',''," . "'$type','[A-Time]$Args::args{'note'}'\n"; Print::log_host_inv( "$img_sh: A-Time note added for meta $Args::args{'meta'}"); print "A-Time sequence event added
\n"; } if ((exists $Args::args{'ctime'}) && ($Args::args{'ctime'} == 1)) { my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime($ctime); $year += 1900; $mon += 1; $mday = "0$mday" if ($mday < 10); $hour = "0$hour" if ($hour < 10); $min = "0$min" if ($min < 10); $sec = "0$sec" if ($sec < 10); print NOTES "'$year','$mon','$mday','$hour','$min','$sec'," . "'$Args::args{'host'}','$vol','$fname','$meta',''," . "'$type','[C-Time]$Args::args{'note'}'\n"; Print::log_host_inv( "$img_sh: C-Time note added for meta $Args::args{'meta'}"); print "C-Time sequence event added
\n"; } close(NOTES); print "


\n" . "You can view the notes and events from the Host Manager View

"; if ((exists $Args::args{'norm_note'}) && ($Args::args{'norm_note'} == 1)) { print "" . "\"View\n"; } print "" . "\"Event\n"; Print::print_html_footer(); return 0; } # Display the contents of the "normal" notes file sub read_norm { Print::print_html_header("Contents of Notes File"); my $notes_file = investig_notes_fname(); Print::log_host_inv("Viewing contents of notes file ($notes_file)"); if ((!(-e "$notes_file")) || (-z "$notes_file")) { print "No notes have been entered yet.
\n" . "They can be entered using the Add Note link within each analysis mode.
\n"; return; } open NOTES, "<$notes_file" or die "Can't open log: $notes_file"; my $file = ""; my $dir = ""; print "\n" . "\n\n
\n"; my $row = 0; # This will need to change whenever the log format changes while () { # we need to extract mnt from here $file = $1 if (/^File: (.*)$/); $dir = $1 if (/^Directory: (.*)$/); # Reset the $file if we are at the end of the current note if (/^\-+$/) { $file = ""; $dir = ""; if (($row++ % 2) == 0) { print "
\n"; } else { print "
\n"; } } else { print "$_
"; } if (/^Volume: ($::REG_VNAME) Meta: ([0-9\-]+)/o) { $vol = $1; $meta = $2; next unless (exists $Caseman::vol2cat{$vol}); # file note if ($file ne "") { # extract the prepended mnt value my $mnt = $Caseman::vol2mnt{$vol}; my $fname = ""; $fname = $1 if ($file =~ /^$mnt\/?(.*)$/); print "" . "\"view\"
\n"; } # directory note elsif ($dir ne "") { # extract the prepended mnt value my $mnt = $Caseman::vol2mnt{$vol}; my $fname = ""; $fname = $1 if ($dir =~ /^$mnt\/?(.*)$/); print "" . "\"view\"
\n"; } # meta note else { print "" . "\"view\"
\n"; } } # block note elsif (/^Volume: ($::REG_VNAME) \w+: ([0-9]+) Len: (\d+)/o) { $vol = $1; $blk = $2; $len = $3; next unless (exists $Caseman::vol2cat{$vol}); print "" . "\"view\"
\n"; } } print "
\n"; # Ok and refresh buttons print "

\n" . "
\n" . "" . "\"close\"\n" . "\n" . "" . "\"refresh\"\n" . "
\n"; close(NOTES); Print::print_html_footer(); return 0; } ######################################################################### # Sequencer Code # Write a sequence event that was manually entered sub write_seq_man { Args::check_note(); Print::print_html_header("Writing Sequencer Event"); # Get rid of carriage returns that Netscape adds $Args::args{'note'} =~ tr/\r//d; $Args::args{'note'} =~ s/\n/
/gs; if ($Args::args{'note'} eq "") { Print::print_err("A comment must be given for the event
\n" . "

" . ""); } # Check the args and add them to the final string that will be written my $str = ""; unless ((exists $Args::args{'year'}) && ($Args::args{'year'} =~ /^(\d\d\d\d)$/)) { Print::print_err("Invalid year
"); } $str .= "'$1',"; unless ((exists $Args::args{'mon'}) && ($Args::args{'mon'} =~ /^(\d\d?)$/)) { Print::print_err("Invalid month
"); } $str .= "'$1',"; unless ((exists $Args::args{'day'}) && ($Args::args{'day'} =~ /^(\d\d?)$/)) { Print::print_err("Invalid day
"); } $str .= "'$1',"; unless ((exists $Args::args{'hour'}) && ($Args::args{'hour'} =~ /^(\d\d?)$/)) { Print::print_err("Invalid hour
"); } $str .= "'$1',"; unless ((exists $Args::args{'min'}) && ($Args::args{'min'} =~ /^(\d\d?)$/)) { Print::print_err("Invalid min
"); } $str .= "'$1',"; unless ((exists $Args::args{'sec'}) && ($Args::args{'sec'} =~ /^(\d\d?)$/)) { Print::print_err("Invalid sec
"); } $str .= "'$1',"; # There are no image, meta, file name, or data unit for this type $str .= "'$Args::args{'host'}','','','','',"; unless ((exists $Args::args{'src'}) && ($Args::args{'src'} =~ /^(\w+)$/)) { Print::print_err("Invalid src
"); } $str .= "'$1','$Args::args{'note'}'\n"; # Write the string to the notes file my $notes_file = investig_seq_notes_fname(); open NOTES, ">>$notes_file" or die "Can't open log: $notes_file"; print NOTES $str; close(NOTES); # Send a message to the user print "Event Added to Sequencer file:

\n" . "$::d2m[$Args::args{'mon'}] $Args::args{'day'}, $Args::args{'year'} " . "$Args::args{'hour'}:$Args::args{'min'}:$Args::args{'sec'}

\n" . "$Args::args{'note'}
\n" . "

" . "\"Ok\"\n"; Print::print_html_footer(); return 0; } # View the sequencer file sub read_seq { Print::print_html_header("Event Sequencer"); print "

\n" . "

Event Sequencer

\n"; my $cnt = 0; my @entry; my ( @year, @mon, @day, @hour, @min, @sec, @host, @vol, @fname, @meta, @data, @type, @note ); # Read the sequencer file into arrays that will be sorted my $notes_file = investig_seq_notes_fname(); if (-e $notes_file) { open NOTES, "$notes_file" or die "Can't open log: $notes_file"; while () { unless ( /^'?(\d+)'?,'?(\d+)'?,'?(\d+)'?,'?(\d+)'?,'?(\d+)'?,'?(\d+)'?,'?($::REG_HOST)'?,'?($::REG_VNAME)?'?,'?(.*?)'?,'?($::REG_META)?'?,'?(\d+)?'?,'?([\w\s]+)'?,'?(.*?)'?$/ ) { Print::print_err("Error parsing sequence event entry: $_"); } $year[$cnt] = $1; $mon[$cnt] = $2; $day[$cnt] = $3; $hour[$cnt] = $4; $min[$cnt] = $5; $sec[$cnt] = $6; $host[$cnt] = $7; $vol[$cnt] = $8; $fname[$cnt] = ""; $fname[$cnt] = $9 if (defined $9); $meta[$cnt] = ""; $meta[$cnt] = $10 if (defined $10); $data[$cnt] = ""; $data[$cnt] = $11 if (defined $11); $type[$cnt] = $12; $note[$cnt] = $13; $entry[$cnt] = $cnt; $cnt++; } close(NOTES); # Sort the values by date, source, and then note my @sorted = sort { $year[$a] <=> $year[$b] or $mon[$a] <=> $mon[$b] or $day[$a] <=> $day[$b] or $hour[$a] <=> $hour[$b] or $min[$a] <=> $min[$b] or $sec[$a] <=> $sec[$b] or lc($type[$a]) cmp lc($type[$b]) or lc($note[$a]) cmp lc($note[$b]) } @entry; # Table and header print "\n" . "\n" . "\n" . "\n" . "\n"; # Cycle through the sorted events my $row = 0; foreach my $i (@sorted) { # Alternate row colors if (($row % 2) == 0) { print "\n"; } else { print "\n"; } # Date & Time print "" . "\n"; # Print the actual note $note[$i] = " " if ($note[$i] eq ""); print "\n"; $row++; } print "
Date & TimeSourceEvent & Note
\n" . "$::d2m[$mon[$i]] $day[$i], $year[$i]" . " $hour[$i]:$min[$i]:$sec[$i]\n"; # If there is as name, then we will show it # @@@ Why does an error message come up from here: # Use of uninitialized value in string ne at if ($fname[$i] ne "") { if ( (exists $vol[$i]) && (defined $vol[$i]) && ($vol[$i] ne "") && (exists $Caseman::vol2mnt{$vol[$i]}) && (exists $meta[$i])) { # extract the prepended mnt value my $mnt = $Caseman::vol2mnt{$vol[$i]}; my $fname = ""; $fname = $1 if ($fname[$i] =~ /^$mnt\/?(.*)$/); # Check if it is a directory if ($type[$i] eq 'dir') { print "\n" . "$fname[$i]\n"; } else { print "\n" . "$fname[$i]\n"; } } else { print "$fname[$i]\n"; } } # Display the meta value if there was no name elsif (($vol[$i] ne "") && (defined $meta[$i]) && ($meta[$i] ne "")) { my $ftype = $Caseman::vol2ftype{$vol[$i]}; # Include a link if we can if (exists $Caseman::vol2mnt{$vol[$i]}) { print "\n" . "$Fs::meta_str{$ftype}: $meta[$i]\n"; } else { print "$Fs::meta_str{$ftype}: $meta[$i]\n"; } } # Otherwise, just give the source type else { print "$type[$i]\n"; } print "$note[$i]
\n"; } # End of if file exists else { print "No events currently exist
\n"; } # Ok and refresh buttons print "

\n" . "
\n" . "" . "\"close\"\n" . "\n" . "" . "\"refresh\"\n" . "
\n"; # Manually add a new event print "


\n" . "Add a New Event

\n" . "
\n" . "
\n" . "\n" . "\n" . Args::make_hidden(); # Month print "\n" . "\n"; # Type print "\n" . "\n"; print "
\n"; print "

Date: " . "\n"; # Day print " \n"; # Year $prev = 1900 + (localtime())[5]; $prev = $Args::args{'year'} if ((exists $Args::args{'year'}) && ($Args::args{'year'} =~ /^\d+$/)); print " \n"; # Hour print "  \n"; # Min print ":\n"; # Sec print ":

 
Event Source:
 
\n
\n"; Print::print_html_footer(); return 0; } # Conver the 'image' format to the 'volume' format sub convert { my %img2vol = %{shift()}; my @invs = Caseman::read_invest(); if (scalar @invs == 0) { push @invs, "unknown"; } foreach $i (@invs) { my $notes_file = "$::host_dir" . "$::LOGDIR/$i.notes"; if ((!(-e "$notes_file")) || (-z "$notes_file")) { next; } Print::log_host_info( "Converting format of notes file for $i ($notes_file)"); open NOTES, "<$notes_file" or die "Can't open log: $notes_file"; my $notes_file_new = $notes_file . ".new"; open NOTES_NEW, ">$notes_file_new" or die "Can't open writing log: $notes_file_new"; while () { if (/Image: ($::REG_IMG)\s+(.*)$/) { my $img = $1; my $addr = $2; unless (exists $img2vol{$img}) { print STDERR "Error finding image during notes conversion: $img. Not converting\n"; next; } my $vol = $img2vol{$img}; # Convert old description to last versions $addr =~ s/Inode:/Meta:/; print NOTES_NEW "Volume: $vol $addr\n"; } else { print NOTES_NEW $_; } } close(NOTES); close(NOTES_NEW); rename $notes_file, $notes_file . ".bak"; rename $notes_file_new, $notes_file; } # NOw do sequence notes foreach $i (@invs) { my $notes_file = "$::host_dir" . "$::LOGDIR/$i.seq.notes"; if ((!(-e "$notes_file")) || (-z "$notes_file")) { next; } open NOTES, "$notes_file" or die "Can't open log: $notes_file"; $notes_file_new = $notes_file . ".new"; open NOTES_NEW, ">$notes_file_new" or die "Can't open log for updating: $notes_file_new"; while () { # No image in entry if (/^'\d+','\d+','\d+','\d+','\d+','\d+','$::REG_HOST','','/) { print NOTES_NEW $_; } elsif ( /^('\d+','\d+','\d+','\d+','\d+','\d+','$::REG_HOST',')($::REG_IMG)(','.*)$/ ) { my $pre = $1; my $img = $2; my $post = $3; unless (exists $img2vol{$img}) { print STDERR "Error finding image during notes conversion: $img. Not converting\n"; next; } my $vol = $img2vol{$img}; print NOTES_NEW $pre . $vol . $post . "\n"; } else { print NOTES_NEW "$_"; return; } } close(NOTES); close(NOTES_NEW); rename $notes_file, $notes_file . ".bak"; rename $notes_file_new, $notes_file; } return 0; }