File Coverage

blib/lib/File/IgnoreReadonly.pm
Criterion Covered Total %
statement 21 30 70.0
branch 4 8 50.0
condition 3 9 33.3
subroutine 8 8 100.0
pod 1 1 100.0
total 37 56 66.0


line stmt bran cond sub pod time code
1             package File::IgnoreReadonly;
2              
3             =pod
4              
5             =head1 NAME
6              
7             File::IgnoreReadonly - Temporarily ensure a file is writable, even if it is readonly
8              
9             =head1 SYNOPSIS
10              
11             SCOPE: {
12             # Make writable, if possible (dies on error)
13             my $guard = File::IgnoreReadonly->new( 'readonly.txt' );
14            
15             # Change the file
16             open( FILE, '>readonly.txt' ) or die "open: $!";
17             print FILE "New Content";
18             close( FILE );
19             }
20            
21             # File is now readonly again
22              
23             =head1 DESCRIPTION
24              
25             This is a convenience package for use in situations that require you to
26             make modifications to files, even if those files are readonly.
27              
28             Typical scenarios include tweaking files in software build systems, where
29             some files will have been generated that are readonly, but you need to be
30             able to make small tweaks to them anyways.
31              
32             While it is certainly possible to simply set a file non-readonly (if it is
33             readonly) and then set it back to readonly again afterwards, doing this in
34             many places can get laborious and looks visually messy.
35              
36             B allows for the creation of a simple guard object that
37             will ensure a file is NOT set readonly (across multiple different operating
38             systems).
39              
40             When the object is DESTROY'ed at the end of the current scope, the file
41             will be returned to the original file permissions it had when the guard
42             object was created.
43              
44             =head1 METHODS
45              
46             =cut
47              
48 2     2   33204 use 5.006;
  2         8  
  2         103  
49 2     2   13 use strict;
  2         3  
  2         76  
50 2     2   19 use vars qw{$VERSION};
  2         6  
  2         112  
51             BEGIN {
52 2     2   56 $VERSION = '0.01';
53             }
54              
55             # Deal with platform issues
56 2     2   18 use constant WIN32 => $^O eq 'MSWin32';
  2         4  
  2         237  
57             BEGIN {
58 2     2   4 if ( WIN32 ) {
59             require Win32::File::Object;
60             } else {
61 2         1882 require File::chmod;
62             }
63             }
64              
65              
66              
67              
68              
69             #####################################################################
70             # Constructor
71              
72             =pod
73              
74             =head2 new
75              
76             The C method is a simple constructor that takes a single parameter.
77              
78             It will set the file to writable if needed, and return a guard object.
79              
80             When the guard object is DESTROYed, the file will be set back to the
81             original file mode.
82              
83             Returns a new B object, or throws an exception (dies)
84             on error.
85              
86             =cut
87              
88             sub new {
89 1     1 1 2292 my ( $class, $file ) = @_;
90 1 50 33     37 unless ( defined $file and ! ref $file and length $file and -f $file ) {
      33        
      33        
91 0         0 Carp::croak("Missing or invalid file name");
92             }
93              
94             # Create the object
95 1         6 my $self = bless {
96             file => $file,
97             }, $class;
98              
99             # If the file is already writable, we don't need to do anything
100 1 50       19 if ( -w $file ) {
101 1         3 return $self;
102             }
103              
104             # On Win32, set readonly false and save the handle object
105 0         0 if ( WIN32 ) {
106             $self->{win32} = Win32::File::Object->new( $file, 1 );
107             $self->{win32}->readonly(0);
108             } else {
109             # Otherwise, save the original file mode
110 0         0 $self->{unix} = (File::chmod::getmod( $file ))[0];
111 0         0 File::chmod::chmod('ug+w', $file );
112             }
113 0         0 return $self;
114             }
115              
116             sub DESTROY {
117 1 50   1   1740 if ( $_[0]->{win32} ) {
    50          
118 0           $_[0]->{win32}->readonly(1);
119 0           delete $_[0]->{win32};
120             } elsif ( $_[0]->{unix} ) {
121 0           chmod( $_[0]->{unix}, $_[0]->{file} );
122 0           delete $_[0]->{unix};
123             }
124             }
125              
126             1;
127              
128             =pod
129              
130             =head1 SUPPORT
131              
132             Bugs should be reported via the CPAN bug tracker at
133              
134             L
135              
136             For other issues, or commercial enhancement or support, contact the author.
137              
138             =head1 AUTHOR
139              
140             Adam Kennedy Eadamk@cpan.orgE
141              
142             =head1 COPYRIGHT
143              
144             Copyright 2008 Adam Kennedy.
145              
146             This program is free software; you can redistribute
147             it and/or modify it under the same terms as Perl itself.
148              
149             The full text of the license can be found in the
150             LICENSE file included with this module.
151              
152             =cut