comparison variant_effect_predictor/Bio/Root/IO.pm @ 0:1f6dce3d34e0

Uploaded
author mahtabm
date Thu, 11 Apr 2013 02:01:53 -0400
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:1f6dce3d34e0
1 # $Id: IO.pm,v 1.37.2.3 2003/06/28 21:57:04 jason Exp $
2 #
3 # BioPerl module for Bio::Root::IO
4 #
5 # Cared for by Hilmar Lapp <hlapp@gmx.net>
6 #
7 # Copyright Hilmar Lapp
8 #
9 # You may distribute this module under the same terms as perl itself
10
11 # POD documentation - main docs before the code
12
13 =head1 NAME
14
15 Bio::Root::IO - module providing several methods often needed when dealing with file IO
16
17 =head1 SYNOPSIS
18
19 # utilize stream I/O in your module
20 $self->{'io'} = Bio::Root::IO->new(-file => "myfile");
21 $self->{'io'}->_print("some stuff");
22 $line = $self->{'io'}->_readline();
23 $self->{'io'}->_pushback($line);
24 $self->{'io'}->close();
25
26 # obtain platform-compatible filenames
27 $path = Bio::Root::IO->catfile($dir, $subdir, $filename);
28 # obtain a temporary file (created in $TEMPDIR)
29 ($handle) = $io->tempfile();
30
31 =head1 DESCRIPTION
32
33 This module provides methods that will usually be needed for any sort
34 of file- or stream-related input/output, e.g., keeping track of a file
35 handle, transient printing and reading from the file handle, a close
36 method, automatically closing the handle on garbage collection, etc.
37
38 To use this for your own code you will either want to inherit from
39 this module, or instantiate an object for every file or stream you are
40 dealing with. In the first case this module will most likely not be
41 the first class off which your class inherits; therefore you need to
42 call _initialize_io() with the named parameters in order to set file
43 handle, open file, etc automatically.
44
45 Most methods start with an underscore, indicating they are private. In
46 OO speak, they are not private but protected, that is, use them in
47 your module code, but a client code of your module will usually not
48 want to call them (except those not starting with an underscore).
49
50 In addition this module contains a couple of convenience methods for
51 cross-platform safe tempfile creation and similar tasks. There are
52 some CPAN modules related that may not be available on all
53 platforms. At present, File::Spec and File::Temp are attempted. This
54 module defines $PATHSEP, $TEMPDIR, and $ROOTDIR, which will always be set,
55 and $OPENFLAGS, which will be set if either of File::Spec or File::Temp fails.
56
57 The -noclose boolean (accessed via the noclose method) prevents a
58 filehandle from being closed when the IO object is cleaned up. This
59 is special behavior when a object like a parser might share a
60 filehandle with an object like an indexer where it is not proper to
61 close the filehandle as it will continue to be reused until the end of the
62 stream is reached. In general you won't want to play with this flag.
63
64 =head1 FEEDBACK
65
66 =head2 Mailing Lists
67
68 User feedback is an integral part of the evolution of this
69 and other Bioperl modules. Send your comments and suggestions preferably
70 to one of the Bioperl mailing lists.
71 Your participation is much appreciated.
72
73 bioperl-l@bioperl.org - General discussion
74 http://bio.perl.org/MailList.html - About the mailing lists
75
76 =head2 Reporting Bugs
77
78 Report bugs to the Bioperl bug tracking system to help us keep track
79 the bugs and their resolution.
80 Bug reports can be submitted via email or the web:
81
82 bioperl-bugs@bio.perl.org
83 http://bugzilla.bioperl.org/
84
85 =head1 AUTHOR - Hilmar Lapp
86
87 Email hlapp@gmx.net
88
89 Describe contact details here
90
91 =head1 APPENDIX
92
93 The rest of the documentation details each of the object methods. Internal methods are usually preceded with a _
94
95 =cut
96
97
98 # Let the code begin...
99
100
101 package Bio::Root::IO;
102 use vars qw(@ISA $FILESPECLOADED $FILETEMPLOADED $FILEPATHLOADED
103 $TEMPDIR $PATHSEP $ROOTDIR $OPENFLAGS $VERBOSE);
104 use strict;
105
106 use Symbol;
107 use POSIX qw(dup);
108 use IO::Handle;
109 use Bio::Root::Root;
110
111 @ISA = qw(Bio::Root::Root);
112
113 my $TEMPCOUNTER;
114 my $HAS_WIN32 = 0;
115
116 BEGIN {
117 $TEMPCOUNTER = 0;
118 $FILESPECLOADED = 0;
119 $FILETEMPLOADED = 0;
120 $FILEPATHLOADED = 0;
121 $VERBOSE = 1;
122
123 # try to load those modules that may cause trouble on some systems
124 eval {
125 require File::Path;
126 $FILEPATHLOADED = 1;
127 };
128 if( $@ ) {
129 print STDERR "Cannot load File::Path: $@" if( $VERBOSE > 0 );
130 # do nothing
131 }
132
133
134 # If on Win32, attempt to find Win32 package
135
136 if($^O =~ /mswin/i) {
137 eval {
138 require Win32;
139 $HAS_WIN32 = 1;
140 };
141 }
142
143 # Try to provide a path separator. Why doesn't File::Spec export this,
144 # or did I miss it?
145 if($^O =~ /mswin/i) {
146 $PATHSEP = "\\";
147 } elsif($^O =~ /macos/i) {
148 $PATHSEP = ":";
149 } else { # unix
150 $PATHSEP = "/";
151 }
152 eval {
153 require File::Spec;
154 $FILESPECLOADED = 1;
155 $TEMPDIR = File::Spec->tmpdir();
156 $ROOTDIR = File::Spec->rootdir();
157 require File::Temp; # tempfile creation
158 $FILETEMPLOADED = 1;
159 };
160 if( $@ ) {
161 if(! defined($TEMPDIR)) { # File::Spec failed
162 # determine tempdir
163 if (defined $ENV{'TEMPDIR'} && -d $ENV{'TEMPDIR'} ) {
164 $TEMPDIR = $ENV{'TEMPDIR'};
165 } elsif( defined $ENV{'TMPDIR'} && -d $ENV{'TMPDIR'} ) {
166 $TEMPDIR = $ENV{'TMPDIR'};
167 }
168 if($^O =~ /mswin/i) {
169 $TEMPDIR = 'C:\TEMP' unless $TEMPDIR;
170 $ROOTDIR = 'C:';
171 } elsif($^O =~ /macos/i) {
172 $TEMPDIR = "" unless $TEMPDIR; # what is a reasonable default on Macs?
173 $ROOTDIR = ""; # what is reasonable??
174 } else { # unix
175 $TEMPDIR = "/tmp" unless $TEMPDIR;
176 $ROOTDIR = "/";
177 }
178 if (!( -d $TEMPDIR && -w $TEMPDIR )) {
179 $TEMPDIR = '.'; # last resort
180 }
181 }
182 # File::Temp failed (alone, or File::Spec already failed)
183 #
184 # determine open flags for tempfile creation -- we'll have to do this
185 # ourselves
186 use Fcntl;
187 use Symbol;
188 $OPENFLAGS = O_CREAT | O_EXCL | O_RDWR;
189 for my $oflag (qw/FOLLOW BINARY LARGEFILE EXLOCK NOINHERIT TEMPORARY/){
190 my ($bit, $func) = (0, "Fcntl::O_" . $oflag);
191 no strict 'refs';
192 $OPENFLAGS |= $bit if eval { $bit = &$func(); 1 };
193 }
194 }
195 }
196
197 =head2 new
198
199 Title : new
200 Usage :
201 Function: Overridden here to automatically call _initialize_io().
202 Example :
203 Returns : new instance of this class
204 Args : named parameters
205
206
207 =cut
208
209 sub new {
210 my ($caller, @args) = @_;
211 my $self = $caller->SUPER::new(@args);
212
213 $self->_initialize_io(@args);
214 return $self;
215 }
216
217 =head2 _initialize_io
218
219 Title : initialize_io
220 Usage : $self->_initialize_io(@params);
221 Function: Initializes filehandle and other properties from the parameters.
222
223 Currently recognizes the following named parameters:
224 -file name of file to open
225 -input name of file, or GLOB, or IO::Handle object
226 -fh file handle (mutually exclusive with -file)
227 -flush boolean flag to autoflush after each write
228 -noclose boolean flag, when set to true will not close a
229 filehandle (must explictly call close($io->_fh)
230 Returns : TRUE
231 Args : named parameters
232
233
234 =cut
235
236 sub _initialize_io {
237 my($self, @args) = @_;
238
239 $self->_register_for_cleanup(\&_io_cleanup);
240
241 my ($input, $noclose, $file, $fh, $flush) = $self->_rearrange([qw(INPUT
242 NOCLOSE
243 FILE FH
244 FLUSH)], @args);
245
246 delete $self->{'_readbuffer'};
247 delete $self->{'_filehandle'};
248 $self->noclose( $noclose) if defined $noclose;
249 # determine whether the input is a file(name) or a stream
250 if($input) {
251 if(ref(\$input) eq "SCALAR") {
252 # we assume that a scalar is a filename
253 if($file && ($file ne $input)) {
254 $self->throw("input file given twice: $file and $input disagree");
255 }
256 $file = $input;
257 } elsif(ref($input) &&
258 ((ref($input) eq "GLOB") || $input->isa('IO::Handle'))) {
259 # input is a stream
260 $fh = $input;
261 } else {
262 # let's be strict for now
263 $self->throw("unable to determine type of input $input: ".
264 "not string and not GLOB");
265 }
266 }
267 if(defined($file) && defined($fh)) {
268 $self->throw("Providing both a file and a filehandle for reading - only one please!");
269 }
270
271 if(defined($file) && ($file ne '')) {
272 $fh = Symbol::gensym();
273 open ($fh,$file) ||
274 $self->throw("Could not open $file: $!");
275 $self->file($file);
276 }
277 $self->_fh($fh) if $fh; # if not provided, defaults to STDIN and STDOUT
278
279 $self->_flush_on_write(defined $flush ? $flush : 1);
280
281 return 1;
282 }
283
284 =head2 _fh
285
286 Title : _fh
287 Usage : $obj->_fh($newval)
288 Function: Get/set the file handle for the stream encapsulated.
289 Example :
290 Returns : value of _filehandle
291 Args : newvalue (optional)
292
293 =cut
294
295 sub _fh {
296 my ($obj, $value) = @_;
297 if ( defined $value) {
298 $obj->{'_filehandle'} = $value;
299 }
300 return $obj->{'_filehandle'};
301 }
302
303 =head2 mode
304
305 Title : mode
306 Usage : $obj->mode()
307 Function:
308 Example :
309 Returns : mode of filehandle:
310 'r' for readable
311 'w' for writeable
312 '?' if mode could not be determined
313 Args : -force (optional), see notes.
314 Notes : once mode() has been called, the filehandle's mode is cached
315 for further calls to mode(). to override this behavior so
316 that mode() re-checks the filehandle's mode, call with arg
317 -force
318
319 =cut
320
321 sub mode {
322 my ($obj, @arg) = @_;
323 my %param = @arg;
324 return $obj->{'_mode'} if defined $obj->{'_mode'} and !$param{-force};
325
326 print STDERR "testing mode... " if $obj->verbose;
327
328 # we need to dup() the original filehandle because
329 # doing fdopen() calls on an already open handle causes
330 # the handle to go stale. is this going to work for non-unix
331 # filehandles? -allen
332
333 my $fh = Symbol::gensym();
334
335 my $iotest = new IO::Handle;
336
337 #test for a readable filehandle;
338 $iotest->fdopen( dup(fileno($obj->_fh)) , 'r' );
339 if($iotest->error == 0){
340
341 # note the hack here, we actually have to try to read the line
342 # and if we get something, pushback() it into the readbuffer.
343 # this is because solaris and windows xp (others?) don't set
344 # IO::Handle::error. for non-linux the r/w testing is done
345 # inside this read-test, instead of the write test below. ugh.
346
347 if($^O eq 'linux'){
348 $obj->{'_mode'} = 'r';
349 my $line = $iotest->getline;
350 $obj->_pushback($line) if defined $line;
351 $obj->{'_mode'} = defined $line ? 'r' : 'w';
352 return $obj->{'_mode'};
353 } else {
354 my $line = $iotest->getline;
355 $obj->_pushback($line) if defined $line;
356 $obj->{'_mode'} = defined $line ? 'r' : 'w';
357 return $obj->{'_mode'};
358 }
359 }
360 $iotest->clearerr;
361
362 #test for a writeable filehandle;
363 $iotest->fdopen( dup(fileno($obj->_fh)) , 'w' );
364 if($iotest->error == 0){
365 $obj->{'_mode'} = 'w';
366 # return $obj->{'_mode'};
367 }
368
369 #wtf type of filehandle is this?
370 # $obj->{'_mode'} = '?';
371 return $obj->{'_mode'};
372 }
373
374 =head2 file
375
376 Title : file
377 Usage : $obj->file($newval)
378 Function: Get/set the filename, if one has been designated.
379 Example :
380 Returns : value of file
381 Args : newvalue (optional)
382
383
384 =cut
385
386 sub file {
387 my ($obj, $value) = @_;
388 if ( defined $value) {
389 $obj->{'_file'} = $value;
390 }
391 return $obj->{'_file'};
392 }
393
394 =head2 _print
395
396 Title : _print
397 Usage : $obj->_print(@lines)
398 Function:
399 Example :
400 Returns : writes output
401
402 =cut
403
404 sub _print {
405 my $self = shift;
406 my $fh = $self->_fh() || \*STDOUT;
407 print $fh @_;
408 }
409
410 =head2 _readline
411
412 Title : _readline
413 Usage : $obj->_readline(%args)
414 Function: Reads a line of input.
415
416 Note that this method implicitely uses the value of $/ that is
417 in effect when called.
418
419 Note also that the current implementation does not handle pushed
420 back input correctly unless the pushed back input ends with the
421 value of $/.
422
423 Example :
424 Args : Accepts a hash of arguments, currently only -raw is recognized
425 passing (-raw => 1) prevents \r\n sequences from being changed
426 to \n. The default value of -raw is undef, allowing \r\n to be
427 converted to \n.
428 Returns :
429
430 =cut
431
432 sub _readline {
433 my $self = shift;
434 my %param =@_;
435 my $fh = $self->_fh || \*ARGV;
436 my $line;
437
438 # if the buffer been filled by _pushback then return the buffer
439 # contents, rather than read from the filehandle
440 $line = shift @{$self->{'_readbuffer'}} || <$fh>;
441
442 #don't strip line endings if -raw is specified
443 $line =~ s/\r\n/\n/g if( (!$param{-raw}) && (defined $line) );
444
445 return $line;
446 }
447
448 =head2 _pushback
449
450 Title : _pushback
451 Usage : $obj->_pushback($newvalue)
452 Function: puts a line previously read with _readline back into a buffer.
453 buffer can hold as many lines as system memory permits.
454 Example :
455 Returns :
456 Args : newvalue
457
458 =cut
459
460 sub _pushback {
461 my ($obj, $value) = @_;
462
463 $obj->{'_readbuffer'} ||= [];
464 push @{$obj->{'_readbuffer'}}, $value;
465 }
466
467 =head2 close
468
469 Title : close
470 Usage : $io->close()
471 Function: Closes the file handle associated with this IO instance.
472 Will not close the FH if -noclose is specified
473 Returns : none
474 Args : none
475
476 =cut
477
478 sub close {
479 my ($self) = @_;
480 return if $self->noclose; # don't close if we explictly asked not to
481 if( defined $self->{'_filehandle'} ) {
482 $self->flush;
483 return if( \*STDOUT == $self->_fh ||
484 \*STDERR == $self->_fh ||
485 \*STDIN == $self->_fh
486 ); # don't close STDOUT fh
487 if( ! ref($self->{'_filehandle'}) ||
488 ! $self->{'_filehandle'}->isa('IO::String') ) {
489 close($self->{'_filehandle'});
490 }
491 }
492 $self->{'_filehandle'} = undef;
493 delete $self->{'_readbuffer'};
494 }
495
496
497 =head2 flush
498
499 Title : flush
500 Usage : $io->flush()
501 Function: Flushes the filehandle
502 Returns : none
503 Args : none
504
505 =cut
506
507 sub flush {
508 my ($self) = shift;
509
510 if( !defined $self->{'_filehandle'} ) {
511 $self->throw("Attempting to call flush but no filehandle active");
512 }
513
514 if( ref($self->{'_filehandle'}) =~ /GLOB/ ) {
515 my $oldh = select($self->{'_filehandle'});
516 $| = 1;
517 select($oldh);
518 } else {
519 $self->{'_filehandle'}->flush();
520 }
521 }
522
523 =head2 noclose
524
525 Title : noclose
526 Usage : $obj->noclose($newval)
527 Function: Get/Set the NOCLOSE flag - setting this to true will
528 prevent a filehandle from being closed
529 when an object is cleaned up or explicitly closed
530 This is a bit of hack
531 Returns : value of noclose (a scalar)
532 Args : on set, new value (a scalar or undef, optional)
533
534
535 =cut
536
537 sub noclose{
538 my $self = shift;
539
540 return $self->{'_noclose'} = shift if @_;
541 return $self->{'_noclose'};
542 }
543
544 sub _io_cleanup {
545 my ($self) = @_;
546
547 $self->close();
548 my $v = $self->verbose;
549
550 # we are planning to cleanup temp files no matter what
551 if( exists($self->{'_rootio_tempfiles'}) &&
552 ref($self->{'_rootio_tempfiles'}) =~ /array/i) {
553 if( $v > 0 ) {
554 print STDERR "going to remove files ",
555 join(",", @{$self->{'_rootio_tempfiles'}}), "\n";
556 }
557 unlink (@{$self->{'_rootio_tempfiles'}} );
558 }
559 # cleanup if we are not using File::Temp
560 if( $self->{'_cleanuptempdir'} &&
561 exists($self->{'_rootio_tempdirs'}) &&
562 ref($self->{'_rootio_tempdirs'}) =~ /array/i) {
563
564 if( $v > 0 ) {
565 print STDERR "going to remove dirs ",
566 join(",", @{$self->{'_rootio_tempdirs'}}), "\n";
567 }
568 $self->rmtree( $self->{'_rootio_tempdirs'});
569 }
570 }
571
572 =head2 exists_exe
573
574 Title : exists_exe
575 Usage : $exists = $obj->exists_exe('clustalw');
576 $exists = Bio::Root::IO->exists_exe('clustalw')
577 $exists = Bio::Root::IO::exists_exe('clustalw')
578 Function: Determines whether the given executable exists either as file
579 or within the path environment. The latter requires File::Spec
580 to be installed.
581 On Win32-based system, .exe is automatically appended to the program
582 name unless the program name already ends in .exe.
583 Example :
584 Returns : 1 if the given program is callable as an executable, and 0 otherwise
585 Args : the name of the executable
586
587 =cut
588
589 sub exists_exe {
590 my ($self, $exe) = @_;
591 $exe = $self if(!(ref($self) || $exe));
592 $exe .= '.exe' if(($^O =~ /mswin/i) && ($exe !~ /\.(exe|com|bat|cmd)$/i));
593 return $exe if(-e $exe); # full path and exists
594
595 # Ewan's comment. I don't think we need this. People should not be
596 # asking for a program with a pathseparator starting it
597
598 # $exe =~ s/^$PATHSEP//;
599
600 # Not a full path, or does not exist. Let's see whether it's in the path.
601 if($FILESPECLOADED) {
602 foreach my $dir (File::Spec->path()) {
603 my $f = Bio::Root::IO->catfile($dir, $exe);
604 return $f if(-e $f && -x $f );
605 }
606 }
607 return 0;
608 }
609
610 =head2 tempfile
611
612 Title : tempfile
613 Usage : my ($handle,$tempfile) = $io->tempfile();
614 Function: Returns a temporary filename and a handle opened for writing and
615 and reading.
616
617 Caveats : If you do not have File::Temp on your system you should avoid
618 specifying TEMPLATE and SUFFIX. (We don't want to recode
619 everything, okay?)
620 Returns : a 2-element array, consisting of temporary handle and temporary
621 file name
622 Args : named parameters compatible with File::Temp: DIR (defaults to
623 $Bio::Root::IO::TEMPDIR), TEMPLATE, SUFFIX.
624
625 =cut
626
627 #'
628 sub tempfile {
629 my ($self, @args) = @_;
630 my ($tfh, $file);
631 my %params = @args;
632
633 # map between naming with and without dash
634 foreach my $key (keys(%params)) {
635 if( $key =~ /^-/ ) {
636 my $v = $params{$key};
637 delete $params{$key};
638 $params{uc(substr($key,1))} = $v;
639 } else {
640 # this is to upper case
641 my $v = $params{$key};
642 delete $params{$key};
643 $params{uc($key)} = $v;
644 }
645 }
646 $params{'DIR'} = $TEMPDIR if(! exists($params{'DIR'}));
647 unless (exists $params{'UNLINK'} &&
648 defined $params{'UNLINK'} &&
649 ! $params{'UNLINK'} ) {
650 $params{'UNLINK'} = 1;
651 } else { $params{'UNLINK'} = 0 }
652
653 if($FILETEMPLOADED) {
654 if(exists($params{'TEMPLATE'})) {
655 my $template = $params{'TEMPLATE'};
656 delete $params{'TEMPLATE'};
657 ($tfh, $file) = File::Temp::tempfile($template, %params);
658 } else {
659 ($tfh, $file) = File::Temp::tempfile(%params);
660 }
661 } else {
662 my $dir = $params{'DIR'};
663 $file = $self->catfile($dir,
664 (exists($params{'TEMPLATE'}) ?
665 $params{'TEMPLATE'} :
666 sprintf( "%s.%s.%s",
667 $ENV{USER} || 'unknown', $$,
668 $TEMPCOUNTER++)));
669
670 # sneakiness for getting around long filenames on Win32?
671 if( $HAS_WIN32 ) {
672 $file = Win32::GetShortPathName($file);
673 }
674
675 # taken from File::Temp
676 if ($] < 5.006) {
677 $tfh = &Symbol::gensym;
678 }
679 # Try to make sure this will be marked close-on-exec
680 # XXX: Win32 doesn't respect this, nor the proper fcntl,
681 # but may have O_NOINHERIT. This may or may not be in Fcntl.
682 local $^F = 2;
683 # Store callers umask
684 my $umask = umask();
685 # Set a known umaskr
686 umask(066);
687 # Attempt to open the file
688 if ( sysopen($tfh, $file, $OPENFLAGS, 0600) ) {
689 # Reset umask
690 umask($umask);
691 } else {
692 $self->throw("Could not open tempfile $file: $!\n");
693 }
694 }
695
696 if( $params{'UNLINK'} ) {
697 push @{$self->{'_rootio_tempfiles'}}, $file;
698 }
699
700
701 return wantarray ? ($tfh,$file) : $tfh;
702 }
703
704 =head2 tempdir
705
706 Title : tempdir
707 Usage : my ($tempdir) = $io->tempdir(CLEANUP=>1);
708 Function: Creates and returns the name of a new temporary directory.
709
710 Note that you should not use this function for obtaining "the"
711 temp directory. Use $Bio::Root::IO::TEMPDIR for that. Calling this
712 method will in fact create a new directory.
713
714 Returns : The name of a new temporary directory.
715 Args : args - ( key CLEANUP ) indicates whether or not to cleanup
716 dir on object destruction, other keys as specified by File::Temp
717
718 =cut
719
720 sub tempdir {
721 my ( $self, @args ) = @_;
722 if($FILETEMPLOADED && File::Temp->can('tempdir') ) {
723 return File::Temp::tempdir(@args);
724 }
725
726 # we have to do this ourselves, not good
727 #
728 # we are planning to cleanup temp files no matter what
729 my %params = @args;
730 $self->{'_cleanuptempdir'} = ( defined $params{CLEANUP} &&
731 $params{CLEANUP} == 1);
732 my $tdir = $self->catfile($TEMPDIR,
733 sprintf("dir_%s-%s-%s",
734 $ENV{USER} || 'unknown', $$,
735 $TEMPCOUNTER++));
736 mkdir($tdir, 0755);
737 push @{$self->{'_rootio_tempdirs'}}, $tdir;
738 return $tdir;
739 }
740
741 =head2 catfile
742
743 Title : catfile
744 Usage : $path = Bio::Root::IO->catfile(@dirs,$filename);
745 Function: Constructs a full pathname in a cross-platform safe way.
746
747 If File::Spec exists on your system, this routine will merely
748 delegate to it. Otherwise it tries to make a good guess.
749
750 You should use this method whenever you construct a path name
751 from directory and filename. Otherwise you risk cross-platform
752 compatibility of your code.
753
754 You can call this method both as a class and an instance method.
755
756 Returns : a string
757 Args : components of the pathname (directories and filename, NOT an
758 extension)
759
760 =cut
761
762 sub catfile {
763 my ($self, @args) = @_;
764
765 return File::Spec->catfile(@args) if($FILESPECLOADED);
766 # this is clumsy and not very appealing, but how do we specify the
767 # root directory?
768 if($args[0] eq '/') {
769 $args[0] = $ROOTDIR;
770 }
771 return join($PATHSEP, @args);
772 }
773
774 =head2 rmtree
775
776 Title : rmtree
777 Usage : Bio::Root::IO->rmtree($dirname );
778 Function: Remove a full directory tree
779
780 If File::Path exists on your system, this routine will merely
781 delegate to it. Otherwise it runs a local version of that code.
782
783 You should use this method to remove directories which contain
784 files.
785
786 You can call this method both as a class and an instance method.
787
788 Returns : number of files successfully deleted
789 Args : roots - rootdir to delete or reference to list of dirs
790
791 verbose - a boolean value, which if TRUE will cause
792 C<rmtree> to print a message each time it
793 examines a file, giving the name of the file, and
794 indicating whether it's using C<rmdir> or
795 C<unlink> to remove it, or that it's skipping it.
796 (defaults to FALSE)
797
798 safe - a boolean value, which if TRUE will cause C<rmtree>
799 to skip any files to which you do not have delete
800 access (if running under VMS) or write access (if
801 running under another OS). This will change in the
802 future when a criterion for 'delete permission'
803 under OSs other than VMS is settled. (defaults to
804 FALSE)
805
806 =cut
807
808 # taken straight from File::Path VERSION = "1.0403"
809 sub rmtree {
810 my($self,$roots, $verbose, $safe) = @_;
811 if( $FILEPATHLOADED ) {
812 return File::Path::rmtree ($roots, $verbose, $safe);
813 }
814
815 my $force_writeable = ($^O eq 'os2' || $^O eq 'dos' || $^O eq 'MSWin32'
816 || $^O eq 'amigaos');
817 my $Is_VMS = $^O eq 'VMS';
818
819 my(@files);
820 my($count) = 0;
821 $verbose ||= 0;
822 $safe ||= 0;
823 if ( defined($roots) && length($roots) ) {
824 $roots = [$roots] unless ref $roots;
825 } else {
826 $self->warn("No root path(s) specified\n");
827 return 0;
828 }
829
830 my($root);
831 foreach $root (@{$roots}) {
832 $root =~ s#/\z##;
833 (undef, undef, my $rp) = lstat $root or next;
834 $rp &= 07777; # don't forget setuid, setgid, sticky bits
835 if ( -d _ ) {
836 # notabene: 0777 is for making readable in the first place,
837 # it's also intended to change it to writable in case we have
838 # to recurse in which case we are better than rm -rf for
839 # subtrees with strange permissions
840 chmod(0777, ($Is_VMS ? VMS::Filespec::fileify($root) : $root))
841 or $self->warn("Can't make directory $root read+writeable: $!")
842 unless $safe;
843 if (opendir(DIR, $root) ){
844 @files = readdir DIR;
845 closedir(DIR);
846 } else {
847 $self->warn( "Can't read $root: $!");
848 @files = ();
849 }
850
851 # Deleting large numbers of files from VMS Files-11 filesystems
852 # is faster if done in reverse ASCIIbetical order
853 @files = reverse @files if $Is_VMS;
854 ($root = VMS::Filespec::unixify($root)) =~ s#\.dir\z## if $Is_VMS;
855 @files = map("$root/$_", grep $_!~/^\.{1,2}\z/s,@files);
856 $count += $self->rmtree([@files],$verbose,$safe);
857 if ($safe &&
858 ($Is_VMS ? !&VMS::Filespec::candelete($root) : !-w $root)) {
859 print "skipped $root\n" if $verbose;
860 next;
861 }
862 chmod 0777, $root
863 or $self->warn( "Can't make directory $root writeable: $!")
864 if $force_writeable;
865 print "rmdir $root\n" if $verbose;
866 if (rmdir $root) {
867 ++$count;
868 }
869 else {
870 $self->warn( "Can't remove directory $root: $!");
871 chmod($rp, ($Is_VMS ? VMS::Filespec::fileify($root) : $root))
872 or $self->warn("and can't restore permissions to "
873 . sprintf("0%o",$rp) . "\n");
874 }
875 }
876 else {
877
878 if ($safe &&
879 ($Is_VMS ? !&VMS::Filespec::candelete($root)
880 : !(-l $root || -w $root)))
881 {
882 print "skipped $root\n" if $verbose;
883 next;
884 }
885 chmod 0666, $root
886 or $self->warn( "Can't make file $root writeable: $!")
887 if $force_writeable;
888 print "unlink $root\n" if $verbose;
889 # delete all versions under VMS
890 for (;;) {
891 unless (unlink $root) {
892 $self->warn( "Can't unlink file $root: $!");
893 if ($force_writeable) {
894 chmod $rp, $root
895 or $self->warn("and can't restore permissions to "
896 . sprintf("0%o",$rp) . "\n");
897 }
898 last;
899 }
900 ++$count;
901 last unless $Is_VMS && lstat $root;
902 }
903 }
904 }
905
906 $count;
907 }
908
909 =head2 _flush_on_write
910
911 Title : _flush_on_write
912 Usage : $obj->_flush_on_write($newval)
913 Function: Boolean flag to indicate whether to flush
914 the filehandle on writing when the end of
915 a component is finished (Sequences,Alignments,etc)
916 Returns : value of _flush_on_write
917 Args : newvalue (optional)
918
919
920 =cut
921
922 sub _flush_on_write {
923 my ($self,$value) = @_;
924 if( defined $value) {
925 $self->{'_flush_on_write'} = $value;
926 }
927 return $self->{'_flush_on_write'};
928 }
929
930 1;