~ubuntu-branches/ubuntu/trusty/bioperl/trusty-proposed

« back to all changes in this revision

Viewing changes to Bio/Root/IO.pm

  • Committer: Bazaar Package Importer
  • Author(s): Charles Plessy
  • Date: 2011-06-17 13:51:18 UTC
  • mfrom: (1.2.5 upstream)
  • Revision ID: james.westby@ubuntu.com-20110617135118-xgpxhaanue57cwqs
Tags: 1.6.901-1
* New upstream release.
* Point debian/watch to search.cpan.org.
* Build using dh and overrides:
  - Use Debhelper 8 (debian/rules, debian/control).
  - Simplified debian/rules.
* Split into libbio-perl-perl, as discussed with the Debian Perl team.
  (debian/control, debian/bioperl.install, debian libbio-perl-perl.install)
* debian/control:
  - Incremented Standards-Version to reflect conformance with Policy 3.9.2.
    No other changes needed.
  - Vcs-Browser URL made redirectable to viewvc.
  - Removed useless ‘svn’ in the Vcs-Svn URL.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# $Id: IO.pm 16147 2009-09-22 01:26:32Z cjfields $
2
1
#
3
2
# BioPerl module for Bio::Root::IO
4
3
#
92
91
the bugs and their resolution.  Bug reports can be submitted via the
93
92
web:
94
93
 
95
 
  http://bugzilla.open-bio.org/
 
94
  https://redmine.open-bio.org/projects/bioperl/
96
95
 
97
96
=head1 AUTHOR - Hilmar Lapp
98
97
 
113
112
 
114
113
 
115
114
package Bio::Root::IO;
116
 
use vars qw($FILESPECLOADED $FILETEMPLOADED $FILEPATHLOADED
117
 
            $TEMPDIR $PATHSEP $ROOTDIR $OPENFLAGS $VERBOSE $ONMAC
118
 
            $HAS_LWP
119
 
           );
 
115
 
 
116
our ($FILESPECLOADED,   $FILETEMPLOADED,
 
117
    $FILEPATHLOADED,    $TEMPDIR,
 
118
    $PATHSEP,           $ROOTDIR,
 
119
    $OPENFLAGS,         $VERBOSE,
 
120
    $ONMAC,             $HAS_LWP,
 
121
    $HAS_EOL);
 
122
 
120
123
use strict;
121
124
 
122
125
use Symbol;
128
131
 
129
132
my $TEMPCOUNTER;
130
133
my $HAS_WIN32 = 0;
131
 
#my $HAS_LWP = 1;
132
134
 
133
135
BEGIN {
134
136
    $TEMPCOUNTER = 0;
139
141
 
140
142
    # try to load those modules that may cause trouble on some systems
141
143
    eval { 
142
 
        require File::Path;
143
 
        $FILEPATHLOADED = 1;
 
144
        require File::Path;
 
145
        $FILEPATHLOADED = 1;
144
146
    }; 
145
147
    if( $@ ) {
146
 
        print STDERR "Cannot load File::Path: $@" if( $VERBOSE > 0 );
147
 
        # do nothing
 
148
        print STDERR "Cannot load File::Path: $@" if( $VERBOSE > 0 );
 
149
        # do nothing
148
150
    }
149
151
 
150
152
    eval {
151
 
        require LWP::UserAgent;
 
153
        require LWP::UserAgent;
152
154
    };
153
155
    if( $@ ) {
154
 
        print STDERR "Cannot load LWP::UserAgent: $@" if( $VERBOSE > 0 );
 
156
        print STDERR "Cannot load LWP::UserAgent: $@" if( $VERBOSE > 0 );
155
157
        $HAS_LWP = 0;
156
158
    } else {
157
159
        $HAS_LWP = 1;
160
162
    # If on Win32, attempt to find Win32 package
161
163
 
162
164
    if($^O =~ /mswin/i) {
163
 
        eval {
164
 
            require Win32;
165
 
            $HAS_WIN32 = 1;
166
 
        };
 
165
    eval {
 
166
        require Win32;
 
167
        $HAS_WIN32 = 1;
 
168
    };
167
169
    }
168
170
 
169
171
    # Try to provide a path separator. Why doesn't File::Spec export this,
170
172
    # or did I miss it?
171
173
    if($^O =~ /mswin/i) {
172
 
        $PATHSEP = "\\";
 
174
        $PATHSEP = "\\";
173
175
    } elsif($^O =~ /macos/i) {
174
 
        $PATHSEP = ":";
 
176
        $PATHSEP = ":";
175
177
    } else { # unix
176
 
        $PATHSEP = "/";
 
178
        $PATHSEP = "/";
177
179
    }
178
180
    eval {
179
 
        require File::Spec;
180
 
        $FILESPECLOADED = 1;
181
 
        $TEMPDIR = File::Spec->tmpdir();
182
 
        $ROOTDIR = File::Spec->rootdir();
183
 
        require File::Temp; # tempfile creation
184
 
        $FILETEMPLOADED = 1;
 
181
        require File::Spec;
 
182
        $FILESPECLOADED = 1;
 
183
        $TEMPDIR = File::Spec->tmpdir();
 
184
        $ROOTDIR = File::Spec->rootdir();
 
185
        require File::Temp; # tempfile creation
 
186
        $FILETEMPLOADED = 1;
185
187
    };
186
188
    if( $@ ) { 
187
 
        if(! defined($TEMPDIR)) { # File::Spec failed
188
 
            # determine tempdir
189
 
            if (defined $ENV{'TEMPDIR'} && -d $ENV{'TEMPDIR'} ) {
190
 
                $TEMPDIR = $ENV{'TEMPDIR'};
191
 
            } elsif( defined $ENV{'TMPDIR'} && -d $ENV{'TMPDIR'} ) {
192
 
                $TEMPDIR = $ENV{'TMPDIR'};
193
 
            }
194
 
            if($^O =~ /mswin/i) {
195
 
                $TEMPDIR = 'C:\TEMP' unless $TEMPDIR;
196
 
                $ROOTDIR = 'C:';
197
 
            } elsif($^O =~ /macos/i) {
198
 
                $TEMPDIR = "" unless $TEMPDIR; # what is a reasonable default on Macs?
199
 
                $ROOTDIR = ""; # what is reasonable??
200
 
            } else { # unix
201
 
                $TEMPDIR = "/tmp" unless $TEMPDIR;
202
 
                $ROOTDIR = "/";
203
 
            }
204
 
            if (!( -d $TEMPDIR && -w $TEMPDIR )) {
205
 
                $TEMPDIR = '.'; # last resort
206
 
            }
207
 
        }
208
 
        # File::Temp failed (alone, or File::Spec already failed)
209
 
        #
210
 
        # determine open flags for tempfile creation -- we'll have to do this
211
 
        # ourselves
212
 
        use Fcntl;
213
 
        use Symbol;
214
 
        $OPENFLAGS = O_CREAT | O_EXCL | O_RDWR;
215
 
        for my $oflag (qw/FOLLOW BINARY LARGEFILE EXLOCK NOINHERIT TEMPORARY/){
216
 
            my ($bit, $func) = (0, "Fcntl::O_" . $oflag);
217
 
            no strict 'refs';
218
 
            $OPENFLAGS |= $bit if eval { $bit = &$func(); 1 };
219
 
        }
 
189
    if(! defined($TEMPDIR)) { # File::Spec failed
 
190
        # determine tempdir
 
191
        if (defined $ENV{'TEMPDIR'} && -d $ENV{'TEMPDIR'} ) {
 
192
            $TEMPDIR = $ENV{'TEMPDIR'};
 
193
        } elsif( defined $ENV{'TMPDIR'} && -d $ENV{'TMPDIR'} ) {
 
194
            $TEMPDIR = $ENV{'TMPDIR'};
 
195
        }
 
196
        if($^O =~ /mswin/i) {
 
197
            $TEMPDIR = 'C:\TEMP' unless $TEMPDIR;
 
198
            $ROOTDIR = 'C:';
 
199
        } elsif($^O =~ /macos/i) {
 
200
            $TEMPDIR = "" unless $TEMPDIR; # what is a reasonable default on Macs?
 
201
            $ROOTDIR = ""; # what is reasonable??
 
202
        } else { # unix
 
203
            $TEMPDIR = "/tmp" unless $TEMPDIR;
 
204
            $ROOTDIR = "/";
 
205
        }
 
206
        if (!( -d $TEMPDIR && -w $TEMPDIR )) {
 
207
            $TEMPDIR = '.'; # last resort
 
208
        }
 
209
    }
 
210
    # File::Temp failed (alone, or File::Spec already failed)
 
211
    #
 
212
    # determine open flags for tempfile creation -- we'll have to do this
 
213
    # ourselves
 
214
    use Fcntl;
 
215
    use Symbol;
 
216
    $OPENFLAGS = O_CREAT | O_EXCL | O_RDWR;
 
217
    for my $oflag (qw/FOLLOW BINARY LARGEFILE EXLOCK NOINHERIT TEMPORARY/){
 
218
        my ($bit, $func) = (0, "Fcntl::O_" . $oflag);
 
219
        no strict 'refs';
 
220
        $OPENFLAGS |= $bit if eval { $bit = &$func(); 1 };
 
221
    }
220
222
    }
221
223
    $ONMAC = "\015" eq "\n";
222
224
}
249
251
 
250
252
           Currently recognizes the following named parameters:
251
253
              -file     name of file to open
 
254
              -string   a string that is to be converted to a filehandle
252
255
              -url      name of URL to open
253
256
              -input    name of file, or GLOB, or IO::Handle object
254
257
              -fh       file handle (mutually exclusive with -file)
255
258
              -flush    boolean flag to autoflush after each write
256
259
              -noclose  boolean flag, when set to true will not close a
257
 
                        filehandle (must explictly call close($io->_fh)
 
260
                        filehandle (must explicitly call close($io->_fh)
258
261
              -retries  number of times to try a web fetch before failure
259
262
                        
260
263
              -ua_parms hashref of key => value parameters to pass 
273
276
 
274
277
    $self->_register_for_cleanup(\&_io_cleanup);
275
278
 
276
 
    my ($input, $noclose, $file, $fh, $flush, $url,
277
 
        $retries, $ua_parms) = 
278
 
        $self->_rearrange([qw(INPUT 
279
 
                              NOCLOSE
280
 
                              FILE 
281
 
                              FH 
282
 
                              FLUSH
283
 
                              URL
284
 
                              RETRIES
285
 
                              UA_PARMS)], @args);
 
279
    my ($input, $noclose, $file, $fh, $string, $flush, $url,
 
280
    $retries, $ua_parms) = 
 
281
    $self->_rearrange([qw(INPUT NOCLOSE FILE FH STRING FLUSH URL RETRIES UA_PARMS)],
 
282
                      @args);
286
283
 
287
284
    if($url){
288
 
        $retries ||= 5;
289
 
 
290
 
      if($HAS_LWP){ #use LWP::UserAgent
291
 
          require LWP::UserAgent;
292
 
          my $ua = LWP::UserAgent->new(%$ua_parms);
293
 
        my $http_result;
294
 
        my($handle,$tempfile) = $self->tempfile();
295
 
        CORE::close($handle);
296
 
          
297
 
 
298
 
        for(my $try = 1 ; $try <= $retries ; $try++){
299
 
            $http_result = $ua->get($url, ':content_file' => $tempfile);
300
 
            $self->warn("[$try/$retries] tried to fetch $url, but server threw " . $http_result->code . ".  retrying...") if !$http_result->is_success;
301
 
            last if $http_result->is_success;
302
 
        }
303
 
          $self->throw("failed to fetch $url, server threw " . $http_result->code) if !$http_result->is_success;
304
 
 
305
 
        $input = $tempfile;
306
 
        $file  = $tempfile;
307
 
      } else { #use Bio::Root::HTTPget
308
 
        #$self->warn("no lwp");
309
 
 
310
 
        $fh = Bio::Root::HTTPget->getFH($url);
311
 
      }
312
 
    }
 
285
        $retries ||= 5;
 
286
    
 
287
        if($HAS_LWP) { #use LWP::UserAgent
 
288
            require LWP::UserAgent;
 
289
            my $ua = LWP::UserAgent->new(%$ua_parms);
 
290
            my $http_result;
 
291
            my($handle,$tempfile) = $self->tempfile();
 
292
            CORE::close($handle);
 
293
          
 
294
    
 
295
            for(my $try = 1 ; $try <= $retries ; $try++){
 
296
                $http_result = $ua->get($url, ':content_file' => $tempfile);
 
297
                $self->warn("[$try/$retries] tried to fetch $url, but server ".
 
298
                            "threw ". $http_result->code . ".  retrying...")
 
299
                            if !$http_result->is_success;
 
300
                last if $http_result->is_success;
 
301
            }
 
302
            $self->throw("failed to fetch $url, server threw ".
 
303
                         $http_result->code) if !$http_result->is_success;
 
304
    
 
305
            $input = $tempfile;
 
306
            $file  = $tempfile;
 
307
        } else { #use Bio::Root::HTTPget
 
308
            #$self->warn("no lwp");
 
309
    
 
310
            $fh = Bio::Root::HTTPget::getFH($url);
 
311
        }
 
312
        }
313
313
 
314
314
    delete $self->{'_readbuffer'};
315
315
    delete $self->{'_filehandle'};
316
316
    $self->noclose( $noclose) if defined $noclose;
317
317
    # determine whether the input is a file(name) or a stream
318
318
    if($input) {
319
 
        if(ref(\$input) eq "SCALAR") {
320
 
            # we assume that a scalar is a filename
321
 
            if($file && ($file ne $input)) {
322
 
                $self->throw("input file given twice: $file and $input disagree");
323
 
            }
324
 
            $file = $input;
325
 
        } elsif(ref($input) &&
326
 
                ((ref($input) eq "GLOB") || $input->isa('IO::Handle'))) {
327
 
            # input is a stream
328
 
            $fh = $input;
329
 
        } else {
330
 
            # let's be strict for now
331
 
            $self->throw("unable to determine type of input $input: ".
332
 
                         "not string and not GLOB");
333
 
        }
 
319
        if(ref(\$input) eq "SCALAR") {
 
320
            # we assume that a scalar is a filename
 
321
            if($file && ($file ne $input)) {
 
322
            $self->throw("input file given twice: $file and $input disagree");
 
323
            }
 
324
            $file = $input;
 
325
        } elsif(ref($input) &&
 
326
            ((ref($input) eq "GLOB") || $input->isa('IO::Handle'))) {
 
327
            # input is a stream
 
328
            $fh = $input;
 
329
        } else {
 
330
            # let's be strict for now
 
331
            $self->throw("unable to determine type of input $input: ".
 
332
                 "not string and not GLOB");
 
333
        }
334
334
    }
 
335
    
335
336
    if(defined($file) && defined($fh)) {
336
 
        $self->throw("Providing both a file and a filehandle for reading - only one please!");
 
337
        $self->throw("Providing both a file and a filehandle for reading - ".
 
338
                     "only one please!");
337
339
    }
338
340
 
 
341
    if ($string) {
 
342
        if(defined($file) || defined($fh)) {
 
343
            $self->throw("File or filehandle provided with -string,".
 
344
                         " please unset if you are using -string as a file");
 
345
        }
 
346
        open($fh, "<", \$string)
 
347
    }
 
348
    
339
349
    if(defined($file) && ($file ne '')) {
340
 
        $fh = Symbol::gensym();
341
 
        open ($fh,$file) ||
342
 
            $self->throw("Could not open $file: $!");
343
 
        $self->file($file);
344
 
    }
345
 
    if ( defined($fh) && !(ref($fh) && ((ref($fh) eq "GLOB") || $fh->isa('IO::Handle') || $fh->isa('IO::String')))  ) {
346
 
        $self->throw("file handle $fh doesn't appear to be a handle");
 
350
        $fh = Symbol::gensym();
 
351
        open ($fh,$file) || $self->throw("Could not open $file: $!");
 
352
        $self->file($file);
 
353
    }
 
354
 
 
355
    if (defined $fh) {
 
356
        # check filehandle to ensure it's one of:
 
357
        # a GLOB reference, as in: open(my $fh, "myfile");
 
358
        # an IO::Handle or IO::String object
 
359
        # the UNIVERSAL::can added to fix Bug2863
 
360
        unless ( ( ref $fh && ( ref $fh eq 'GLOB' ) )
 
361
                 || ( ref $fh && ( UNIVERSAL::can( $fh, 'can' ) 
 
362
                    && ( $fh->isa('IO::Handle') || $fh->isa('IO::String') ) ) ) 
 
363
               ) {
 
364
            $self->throw("file handle $fh doesn't appear to be a handle");
 
365
        }
 
366
    }
 
367
    if ($HAS_EOL) {
 
368
        binmode $fh, ':raw:eol(LF-Native)';
347
369
    }
348
370
    $self->_fh($fh) if $fh; # if not provided, defaults to STDIN and STDOUT
349
371
 
366
388
sub _fh {
367
389
    my ($obj, $value) = @_;
368
390
    if ( defined $value) {
369
 
        $obj->{'_filehandle'} = $value;
 
391
    $obj->{'_filehandle'} = $value;
370
392
    }
371
393
    return $obj->{'_filehandle'};
372
394
}
379
401
 Example :
380
402
 Returns : mode of filehandle:
381
403
           'r' for readable
382
 
           'w' for writeable
 
404
           'w' for writable
383
405
           '?' if mode could not be determined
384
406
 Args    : -force (optional), see notes.
385
407
 Notes   : once mode() has been called, the filehandle's mode is cached
391
413
 
392
414
sub mode {
393
415
    my ($obj, @arg) = @_;
394
 
        my %param = @arg;
 
416
    my %param = @arg;
395
417
    return $obj->{'_mode'} if defined $obj->{'_mode'} and !$param{-force};
396
418
    
397
419
    # Previous system of:
428
450
 Returns : value of file
429
451
 Args    : newvalue (optional)
430
452
 
431
 
 
432
453
=cut
433
454
 
434
455
sub file {
435
456
    my ($obj, $value) = @_;
436
457
    if ( defined $value) {
437
 
        $obj->{'_file'} = $value;
 
458
    $obj->{'_file'} = $value;
438
459
    }
439
460
    return $obj->{'_file'};
440
461
}
456
477
    return $ret;
457
478
}
458
479
 
 
480
 
 
481
=head2 _insert
 
482
 
 
483
    Title   : _insert
 
484
    Usage   : $obj->_insert($string,1)
 
485
    Function: Insert some text in a file at the given line number (1-based).
 
486
    Returns : 1 on success
 
487
    Args    : string to write in file
 
488
              line number to insert the string at
 
489
 
 
490
=cut
 
491
 
 
492
sub _insert {
 
493
    my ($self, $string, $line_num) = @_;
 
494
    # Line number check
 
495
    if ($line_num < 1) {
 
496
        $self->throw("Cannot insert text at line $line_num because the minimum".
 
497
            " line number possible is 1");
 
498
    }
 
499
    # File check
 
500
    my $file = $self->file;
 
501
    if (not defined $file) {
 
502
        $self->throw('Cannot insert a line in a IO object initialized with ".
 
503
            "anything else than a file.');
 
504
    }
 
505
    $file =~ s/^\+?[><]?//; # transform '+>output.ace' into 'output.ace'
 
506
    # Everything that needs to be written is written before we read it
 
507
    $self->flush;
 
508
    # Edit the file in place, line by line (no slurping)
 
509
    {
 
510
        local @ARGV = ($file);     # input file
 
511
        #local $^I = '~';          # backup file extension, e.g. ~, .bak, .ori
 
512
        local $^I = '';            # no backup file
 
513
        while (<>) {
 
514
            if ($. == $line_num) { # right line for new data
 
515
                print $string.$_;
 
516
            } else {
 
517
                print;
 
518
            }
 
519
        }
 
520
    }
 
521
    # Line number check (again)
 
522
    if ( $. > 0 && $line_num > $. ) {
 
523
        $self->throw("Cannot insert text at line $line_num because there are ".
 
524
            "only $. lines in file $file");
 
525
    }
 
526
    # Re-open the file in append mode to be ready to add text at the end of it
 
527
    # when the next _print() statement comes
 
528
    open my $new_fh, ">>$file" or $self->throw("Cannot append to file $file: $!");
 
529
    $self->_fh($new_fh);
 
530
    # If file is empty and we're inserting at line 1, simply append text to file
 
531
    if ( $. == 0 && $line_num == 1 ) {
 
532
        $self->_print($string);
 
533
    }
 
534
    return 1;
 
535
}
 
536
 
 
537
 
459
538
=head2 _readline
460
539
 
461
540
 Title   : _readline
487
566
    # if the buffer been filled by _pushback then return the buffer
488
567
    # contents, rather than read from the filehandle
489
568
    if( @{$self->{'_readbuffer'} || [] } ) {
490
 
        $line = shift @{$self->{'_readbuffer'}};
 
569
    $line = shift @{$self->{'_readbuffer'}};
491
570
    } else {
492
 
        $line = <$fh>;
 
571
    $line = <$fh>;
493
572
    }
494
 
 
 
573
    
495
574
    #don't strip line endings if -raw is specified
496
575
    # $line =~ s/\r\n/\n/g if( (!$param{-raw}) && (defined $line) );
497
576
    # Dave Howorth's fix
498
 
    if( (!$param{-raw}) && (defined $line) ) {
 
577
    if( !$HAS_EOL && !$param{-raw} && (defined $line) ) {
499
578
        $line =~ s/\015\012/\012/g; # Change all CR/LF pairs to LF
500
579
        $line =~ tr/\015/\n/ unless $ONMAC; # Change all single CRs to NEWLINE
501
580
    }
512
591
 Returns : none
513
592
 Args    : newvalue
514
593
 Note    : This is only supported for pushing back data ending with the
515
 
                   current, localized value of $/. Using this method to push modified
516
 
                   data back onto the buffer stack is not supported; see bug 843.
 
594
           current, localized value of $/. Using this method to push modified
 
595
           data back onto the buffer stack is not supported; see bug 843.
517
596
 
518
597
=cut
519
598
 
 
599
# fix for bug 843, this reveals some unsupported behavior
 
600
    
 
601
#sub _pushback {
 
602
#    my ($obj, $value) = @_;    
 
603
#    if (index($value, $/) >= 0) {
 
604
#        push @{$obj->{'_readbuffer'}}, $value;
 
605
#    } else {
 
606
#        $obj->throw("Pushing modifed data back not supported: $value");
 
607
#    }
 
608
#}
 
609
 
520
610
sub _pushback {
521
611
    my ($obj, $value) = @_;
522
612
    return unless $value;
536
626
 
537
627
sub close {
538
628
   my ($self) = @_;
539
 
   return if $self->noclose; # don't close if we explictly asked not to
540
 
   if( defined $self->{'_filehandle'} ) {
 
629
 
 
630
   # don't close if we explicitly asked not to
 
631
   return if $self->noclose;
 
632
 
 
633
   if( defined( my $fh = $self->{'_filehandle'} )) {
541
634
       $self->flush;
542
 
       return if( \*STDOUT == $self->_fh ||
543
 
                  \*STDERR == $self->_fh ||
544
 
                  \*STDIN == $self->_fh
545
 
                  ); # don't close STDOUT fh
546
 
       if( ! ref($self->{'_filehandle'}) ||
547
 
           ! $self->{'_filehandle'}->isa('IO::String') ) {
548
 
           close($self->{'_filehandle'});
549
 
       }
 
635
       return if     ref $fh eq 'GLOB'
 
636
         && (    \*STDOUT == $fh
 
637
              || \*STDERR == $fh
 
638
              || \*STDIN  == $fh
 
639
                    );
 
640
 
 
641
       # don't close IO::Strings
 
642
       close $fh unless ref $fh && $fh->isa('IO::String');
550
643
   }
551
644
   $self->{'_filehandle'} = undef;
552
645
   delete $self->{'_readbuffer'};
607
700
 
608
701
    # we are planning to cleanup temp files no matter what    
609
702
    if( exists($self->{'_rootio_tempfiles'}) &&
610
 
        ref($self->{'_rootio_tempfiles'}) =~ /array/i &&
 
703
    ref($self->{'_rootio_tempfiles'}) =~ /array/i &&
611
704
    !$self->save_tempfiles) { 
612
 
        if( $v > 0 ) {
613
 
            warn( "going to remove files ", 
614
 
                  join(",",  @{$self->{'_rootio_tempfiles'}}), "\n");
615
 
        }
616
 
        unlink  (@{$self->{'_rootio_tempfiles'}} );
 
705
    if( $v > 0 ) {
 
706
        warn( "going to remove files ", 
 
707
          join(",",  @{$self->{'_rootio_tempfiles'}}), "\n");
 
708
    }
 
709
    unlink  (@{$self->{'_rootio_tempfiles'}} );
617
710
    }
618
711
    # cleanup if we are not using File::Temp
619
712
    if( $self->{'_cleanuptempdir'} &&
620
 
        exists($self->{'_rootio_tempdirs'}) &&
621
 
        ref($self->{'_rootio_tempdirs'}) =~ /array/i &&
622
 
    !$self->save_tempfiles) {   
623
 
        if( $v > 0 ) {
624
 
            warn( "going to remove dirs ", 
625
 
                  join(",",  @{$self->{'_rootio_tempdirs'}}), "\n");
626
 
        }
627
 
        $self->rmtree( $self->{'_rootio_tempdirs'});
 
713
    exists($self->{'_rootio_tempdirs'}) &&
 
714
    ref($self->{'_rootio_tempdirs'}) =~ /array/i &&
 
715
    !$self->save_tempfiles) {   
 
716
    if( $v > 0 ) {
 
717
        warn( "going to remove dirs ", 
 
718
          join(",",  @{$self->{'_rootio_tempdirs'}}), "\n");
 
719
    }
 
720
    $self->rmtree( $self->{'_rootio_tempdirs'});
628
721
    }
629
722
}
630
723
 
647
740
 
648
741
sub exists_exe {
649
742
    my ($self, $exe) = @_;
650
 
        $self->throw("Must pass a defined value to exists_exe") unless defined $exe;
 
743
    $self->throw("Must pass a defined value to exists_exe") unless defined $exe;
651
744
    $exe = $self if (!(ref($self) || $exe));
652
745
    $exe .= '.exe' if(($^O =~ /mswin/i) && ($exe !~ /\.(exe|com|bat|cmd)$/i));
653
 
    return $exe if (-e $exe); # full path and exists
 
746
    return $exe if ( -f $exe && -x $exe ); # full path and exists
654
747
 
655
748
    # Ewan's comment. I don't think we need this. People should not be
656
749
    # asking for a program with a pathseparator starting it
657
 
    
658
750
    # $exe =~ s/^$PATHSEP//;
659
751
 
660
752
    # Not a full path, or does not exist. Let's see whether it's in the path.
661
753
    if($FILESPECLOADED) {
662
 
        foreach my $dir (File::Spec->path()) {
663
 
            my $f = Bio::Root::IO->catfile($dir, $exe);     
664
 
            return $f if(-e $f && -x $f );
665
 
        }
666
 
    }    
 
754
        foreach my $dir (File::Spec->path()) {
 
755
            my $f = Bio::Root::IO->catfile($dir, $exe);
 
756
            return $f if( -f $f && -x $f );
 
757
        }
 
758
    }
667
759
    return 0;
668
760
}
669
761
 
692
784
 
693
785
    # map between naming with and without dash
694
786
    foreach my $key (keys(%params)) {
695
 
        if( $key =~ /^-/  ) {
696
 
            my $v = $params{$key};
697
 
            delete $params{$key};
698
 
            $params{uc(substr($key,1))} = $v;
699
 
        } else { 
700
 
            # this is to upper case
701
 
            my $v = $params{$key};
702
 
            delete $params{$key};           
703
 
            $params{uc($key)} = $v;
704
 
        }
 
787
    if( $key =~ /^-/  ) {
 
788
        my $v = $params{$key};
 
789
        delete $params{$key};
 
790
        $params{uc(substr($key,1))} = $v;
 
791
    } else { 
 
792
        # this is to upper case
 
793
        my $v = $params{$key};
 
794
        delete $params{$key};       
 
795
        $params{uc($key)} = $v;
 
796
    }
705
797
    }
706
798
    $params{'DIR'} = $TEMPDIR if(! exists($params{'DIR'}));
707
799
    unless (exists $params{'UNLINK'} && 
708
 
            defined $params{'UNLINK'} &&
709
 
            ! $params{'UNLINK'} ) {
710
 
        $params{'UNLINK'} = 1;
 
800
        defined $params{'UNLINK'} &&
 
801
        ! $params{'UNLINK'} ) {
 
802
    $params{'UNLINK'} = 1;
711
803
    } else { $params{'UNLINK'} = 0 }
712
 
            
 
804
        
713
805
    if($FILETEMPLOADED) {
714
 
        if(exists($params{'TEMPLATE'})) {
715
 
            my $template = $params{'TEMPLATE'};
716
 
            delete $params{'TEMPLATE'};
717
 
            ($tfh, $file) = File::Temp::tempfile($template, %params);
718
 
        } else {
719
 
            ($tfh, $file) = File::Temp::tempfile(%params);
720
 
        }
721
 
    } else {
722
 
        my $dir = $params{'DIR'};
723
 
        $file = $self->catfile($dir,
724
 
                               (exists($params{'TEMPLATE'}) ?
725
 
                                $params{'TEMPLATE'} :
726
 
                                sprintf( "%s.%s.%s",  
727
 
                                         $ENV{USER} || 'unknown', $$, 
728
 
                                         $TEMPCOUNTER++)));
729
 
 
730
 
        # sneakiness for getting around long filenames on Win32?
731
 
        if( $HAS_WIN32 ) {
732
 
            $file = Win32::GetShortPathName($file);
733
 
        }
734
 
 
735
 
        # Try to make sure this will be marked close-on-exec
736
 
        # XXX: Win32 doesn't respect this, nor the proper fcntl,
737
 
        #      but may have O_NOINHERIT. This may or may not be in Fcntl.
738
 
        local $^F = 2; 
739
 
        # Store callers umask
740
 
        my $umask = umask();
741
 
        # Set a known umaskr
742
 
        umask(066);
743
 
        # Attempt to open the file
744
 
        if ( sysopen($tfh, $file, $OPENFLAGS, 0600) ) {
745
 
            # Reset umask
746
 
            umask($umask); 
747
 
        } else { 
748
 
            $self->throw("Could not open tempfile $file: $!\n");
749
 
        }
 
806
    if(exists($params{'TEMPLATE'})) {
 
807
        my $template = $params{'TEMPLATE'};
 
808
        delete $params{'TEMPLATE'};
 
809
        ($tfh, $file) = File::Temp::tempfile($template, %params);
 
810
    } else {
 
811
        ($tfh, $file) = File::Temp::tempfile(%params);
 
812
    }
 
813
    } else {
 
814
    my $dir = $params{'DIR'};
 
815
    $file = $self->catfile($dir,
 
816
                   (exists($params{'TEMPLATE'}) ?
 
817
                $params{'TEMPLATE'} :
 
818
                sprintf( "%s.%s.%s",  
 
819
                     $ENV{USER} || 'unknown', $$, 
 
820
                     $TEMPCOUNTER++)));
 
821
 
 
822
    # sneakiness for getting around long filenames on Win32?
 
823
    if( $HAS_WIN32 ) {
 
824
        $file = Win32::GetShortPathName($file);
 
825
    }
 
826
 
 
827
    # Try to make sure this will be marked close-on-exec
 
828
    # XXX: Win32 doesn't respect this, nor the proper fcntl,
 
829
    #      but may have O_NOINHERIT. This may or may not be in Fcntl.
 
830
    local $^F = 2; 
 
831
    # Store callers umask
 
832
    my $umask = umask();
 
833
    # Set a known umaskr
 
834
    umask(066);
 
835
    # Attempt to open the file
 
836
    if ( sysopen($tfh, $file, $OPENFLAGS, 0600) ) {
 
837
        # Reset umask
 
838
        umask($umask); 
 
839
    } else { 
 
840
        $self->throw("Could not open tempfile $file: $!\n");
 
841
    }
750
842
    }
751
843
 
752
844
    if(  $params{'UNLINK'} ) {
753
 
        push @{$self->{'_rootio_tempfiles'}}, $file;
 
845
    push @{$self->{'_rootio_tempfiles'}}, $file;
754
846
    } 
755
847
 
756
848
 
776
868
sub tempdir {
777
869
    my ( $self, @args ) = @_;
778
870
    if($FILETEMPLOADED && File::Temp->can('tempdir') ) {
779
 
        return File::Temp::tempdir(@args);
 
871
    return File::Temp::tempdir(@args);
780
872
    }
781
873
 
782
874
    # we have to do this ourselves, not good
784
876
    # we are planning to cleanup temp files no matter what
785
877
    my %params = @args;
786
878
    $self->{'_cleanuptempdir'} = ( defined $params{CLEANUP} && 
787
 
                                   $params{CLEANUP} == 1);
 
879
                   $params{CLEANUP} == 1);
788
880
    my $tdir = $self->catfile($TEMPDIR,
789
 
                              sprintf("dir_%s-%s-%s", 
790
 
                                      $ENV{USER} || 'unknown', $$, 
791
 
                                      $TEMPCOUNTER++));
 
881
                  sprintf("dir_%s-%s-%s", 
 
882
                      $ENV{USER} || 'unknown', $$, 
 
883
                      $TEMPCOUNTER++));
792
884
    mkdir($tdir, 0755);
793
885
    push @{$self->{'_rootio_tempdirs'}}, $tdir; 
794
886
    return $tdir;
822
914
    # this is clumsy and not very appealing, but how do we specify the
823
915
    # root directory?
824
916
    if($args[0] eq '/') {
825
 
        $args[0] = $ROOTDIR;
 
917
    $args[0] = $ROOTDIR;
826
918
    }
827
919
    return join($PATHSEP, @args);
828
920
}
865
957
sub rmtree {
866
958
    my($self,$roots, $verbose, $safe) = @_;
867
959
    if( $FILEPATHLOADED ) { 
868
 
        return File::Path::rmtree ($roots, $verbose, $safe);
 
960
    return File::Path::rmtree ($roots, $verbose, $safe);
869
961
    }
870
962
 
871
 
    my $force_writeable = ($^O eq 'os2' || $^O eq 'dos' || $^O eq 'MSWin32'
872
 
                       || $^O eq 'amigaos' || $^O eq 'cygwin');
 
963
    my $force_writable = ($^O eq 'os2' || $^O eq 'dos' || $^O eq 'MSWin32'
 
964
               || $^O eq 'amigaos' || $^O eq 'cygwin');
873
965
    my $Is_VMS = $^O eq 'VMS';
874
966
 
875
967
    my(@files);
877
969
    $verbose ||= 0;
878
970
    $safe ||= 0;
879
971
    if ( defined($roots) && length($roots) ) {
880
 
        $roots = [$roots] unless ref $roots;
 
972
    $roots = [$roots] unless ref $roots;
881
973
    } else {
882
 
        $self->warn("No root path(s) specified\n");
883
 
        return 0;
 
974
    $self->warn("No root path(s) specified\n");
 
975
    return 0;
884
976
    }
885
977
 
886
978
    my($root);
887
979
    foreach $root (@{$roots}) {
888
 
        $root =~ s#/\z##;
889
 
        (undef, undef, my $rp) = lstat $root or next;
890
 
        $rp &= 07777;   # don't forget setuid, setgid, sticky bits
891
 
        if ( -d _ ) {
892
 
            # notabene: 0777 is for making readable in the first place,
893
 
            # it's also intended to change it to writable in case we have
894
 
            # to recurse in which case we are better than rm -rf for 
895
 
            # subtrees with strange permissions
896
 
            chmod(0777, ($Is_VMS ? VMS::Filespec::fileify($root) : $root))
897
 
              or $self->warn("Can't make directory $root read+writeable: $!")
898
 
                unless $safe;
899
 
            if (opendir(DIR, $root) ){
900
 
                @files = readdir DIR;
901
 
                closedir(DIR);
902
 
            } else {
903
 
                $self->warn( "Can't read $root: $!");
904
 
                @files = ();
905
 
            }
906
 
 
907
 
            # Deleting large numbers of files from VMS Files-11 filesystems
908
 
            # is faster if done in reverse ASCIIbetical order 
909
 
            @files = reverse @files if $Is_VMS;
910
 
            ($root = VMS::Filespec::unixify($root)) =~ s#\.dir\z## if $Is_VMS;
911
 
            @files = map("$root/$_", grep $_!~/^\.{1,2}\z/s,@files);
912
 
            $count += $self->rmtree([@files],$verbose,$safe);
913
 
            if ($safe &&
914
 
                ($Is_VMS ? !&VMS::Filespec::candelete($root) : !-w $root)) {
915
 
                print "skipped $root\n" if $verbose;
916
 
                next;
917
 
            }
918
 
            chmod 0777, $root
919
 
              or $self->warn( "Can't make directory $root writeable: $!")
920
 
                if $force_writeable;
921
 
            print "rmdir $root\n" if $verbose;
922
 
            if (rmdir $root) {
923
 
                ++$count;
924
 
            }
925
 
            else {
926
 
                $self->warn( "Can't remove directory $root: $!");
927
 
                chmod($rp, ($Is_VMS ? VMS::Filespec::fileify($root) : $root))
928
 
                    or $self->warn("and can't restore permissions to "
929
 
                            . sprintf("0%o",$rp) . "\n");
930
 
            }
931
 
        }
932
 
        else {
933
 
 
934
 
            if ($safe &&
935
 
                ($Is_VMS ? !&VMS::Filespec::candelete($root)
936
 
                         : !(-l $root || -w $root)))
937
 
            {
938
 
                print "skipped $root\n" if $verbose;
939
 
                next;
940
 
            }
941
 
            chmod 0666, $root
942
 
              or $self->warn( "Can't make file $root writeable: $!")
943
 
                if $force_writeable;
944
 
            warn "unlink $root\n" if $verbose;
945
 
            # delete all versions under VMS
946
 
            for (;;) {
947
 
                unless (unlink $root) {
948
 
                    $self->warn( "Can't unlink file $root: $!");
949
 
                    if ($force_writeable) {
950
 
                        chmod $rp, $root
951
 
                            or $self->warn("and can't restore permissions to "
952
 
                                    . sprintf("0%o",$rp) . "\n");
953
 
                    }
954
 
                    last;
955
 
                }
956
 
                ++$count;
957
 
                last unless $Is_VMS && lstat $root;
958
 
            }
959
 
        }
 
980
    $root =~ s#/\z##;
 
981
    (undef, undef, my $rp) = lstat $root or next;
 
982
    $rp &= 07777;   # don't forget setuid, setgid, sticky bits
 
983
    if ( -d _ ) {
 
984
        # notabene: 0777 is for making readable in the first place,
 
985
        # it's also intended to change it to writable in case we have
 
986
        # to recurse in which case we are better than rm -rf for 
 
987
        # subtrees with strange permissions
 
988
        chmod(0777, ($Is_VMS ? VMS::Filespec::fileify($root) : $root))
 
989
          or $self->warn("Can't make directory $root read+writable: $!")
 
990
        unless $safe;
 
991
        if (opendir(DIR, $root) ){
 
992
        @files = readdir DIR;
 
993
        closedir(DIR);
 
994
        } else {
 
995
            $self->warn( "Can't read $root: $!");
 
996
        @files = ();
 
997
        }
 
998
 
 
999
        # Deleting large numbers of files from VMS Files-11 filesystems
 
1000
        # is faster if done in reverse ASCIIbetical order 
 
1001
        @files = reverse @files if $Is_VMS;
 
1002
        ($root = VMS::Filespec::unixify($root)) =~ s#\.dir\z## if $Is_VMS;
 
1003
        @files = map("$root/$_", grep $_!~/^\.{1,2}\z/s,@files);
 
1004
        $count += $self->rmtree([@files],$verbose,$safe);
 
1005
        if ($safe &&
 
1006
        ($Is_VMS ? !&VMS::Filespec::candelete($root) : !-w $root)) {
 
1007
        print "skipped $root\n" if $verbose;
 
1008
        next;
 
1009
        }
 
1010
        chmod 0777, $root
 
1011
          or $self->warn( "Can't make directory $root writable: $!")
 
1012
        if $force_writable;
 
1013
        print "rmdir $root\n" if $verbose;
 
1014
        if (rmdir $root) {
 
1015
        ++$count;
 
1016
        }
 
1017
        else {
 
1018
        $self->warn( "Can't remove directory $root: $!");
 
1019
        chmod($rp, ($Is_VMS ? VMS::Filespec::fileify($root) : $root))
 
1020
            or $self->warn("and can't restore permissions to "
 
1021
                    . sprintf("0%o",$rp) . "\n");
 
1022
        }
 
1023
    }
 
1024
    else {
 
1025
 
 
1026
        if ($safe &&
 
1027
        ($Is_VMS ? !&VMS::Filespec::candelete($root)
 
1028
                 : !(-l $root || -w $root)))
 
1029
        {
 
1030
        print "skipped $root\n" if $verbose;
 
1031
        next;
 
1032
        }
 
1033
        chmod 0666, $root
 
1034
          or $self->warn( "Can't make file $root writable: $!")
 
1035
        if $force_writable;
 
1036
        warn "unlink $root\n" if $verbose;
 
1037
        # delete all versions under VMS
 
1038
        for (;;) {
 
1039
        unless (unlink $root) {
 
1040
            $self->warn( "Can't unlink file $root: $!");
 
1041
            if ($force_writable) {
 
1042
            chmod $rp, $root
 
1043
                or $self->warn("and can't restore permissions to "
 
1044
                        . sprintf("0%o",$rp) . "\n");
 
1045
            }
 
1046
            last;
 
1047
        }
 
1048
        ++$count;
 
1049
        last unless $Is_VMS && lstat $root;
 
1050
        }
 
1051
    }
960
1052
    }
961
1053
 
962
1054
    $count;
978
1070
sub _flush_on_write {
979
1071
    my ($self,$value) = @_;
980
1072
    if( defined $value) {
981
 
        $self->{'_flush_on_write'} = $value;
 
1073
    $self->{'_flush_on_write'} = $value;
982
1074
    }
983
1075
    return $self->{'_flush_on_write'};
984
1076
}