File Coverage

lib/File/Access/Driver.pm
Criterion Covered Total %
statement 253 469 53.9
branch 96 298 32.2
condition 5 14 35.7
subroutine 33 46 71.7
pod 9 36 25.0
total 396 863 45.8


line stmt bran cond sub pod time code
1             #
2             # @author Bodo (Hugo) Barwich
3             # @version 2026-03-21
4             # @package File Access Driver
5             # @subpackage lib/File/Access/Driver.pm
6              
7             # This module defines the a class to interact with files
8             #
9             #---------------------------------
10             # Requirements:
11             #
12             #---------------------------------
13             # Extensions:
14             #
15             #---------------------------------
16             # Configurations:
17             #
18             #---------------------------------
19             # Features:
20              
21             #==============================================================================
22             # The File::Access::Driver Package
23              
24             =head1 NAME
25              
26             File::Access::Driver - Convenient File Access with "Batteries included"
27              
28             =cut
29              
30             package File::Access::Driver;
31              
32             our $VERSION = '1.0.2';
33              
34             #----------------------------------------------------------------------------
35             #Dependencies
36              
37 1     1   104794 use Fcntl ':flock'; # import LOCK_* constants
  1         1  
  1         131  
38 1     1   5 use File::Path qw(make_path);
  1         1  
  1         4548  
39              
40             =head1 DESCRIPTION
41              
42             C is a class for convenient file access designed to reduce
43             the code needed to interact with files.
44              
45             It has grown to a "I" solution covering the most file access
46             use cases.
47              
48             It will not produce exceptions but instead report the errors over the C
49             and the C methods.
50              
51             =head1 SYNOPSIS
52              
53             The C can be used as seen in the "I" test:
54              
55             use File::Access::Driver;
56              
57             my $driver = File::Access::Driver->new( 'filepath' => $spath . 'files/out/testfile_out.txt' );
58              
59             # Make sure the file does not exist
60             is( $driver->Delete(), 1, "File Delete: Delete operation 1 correct" );
61             is( $driver->Exists(), 0, "File Exist: File does not exist anymore" );
62              
63             $driver->writeContent(q(This is the multi line content for the test file.
64              
65             It will be written into the test file.
66             The file should only contain this text.
67             Also the file should be created.
68             ));
69              
70             printf(
71             "Test File Exists - File '%s': Write finished with [%d]\n",
72             $driver->getFileName(),
73             $driver->getErrorCode()
74             );
75             printf(
76             "Test File Exists - File '%s': Write Report:\n'%s'\n",
77             $driver->getFileName(),
78             ${ $driver->getReportString() }
79             );
80             printf(
81             "Test File Exists - File '%s': Write Error:\n'%s'\n",
82             $driver->getFileName(),
83             ${ $driver->getErrorString() }
84             );
85              
86             is( $driver->getErrorCode(), 0, "Write Error Code: No errors have occurred" );
87             is( ${ $driver->getErrorString() }, '', "Write Error Message: No errors are reported" );
88              
89             is( $driver->Exists(), 1, "File Exist: File does exist now" );
90             isnt( $driver->getFileSize(), 0, "File Size: File is not empty anymore" );
91              
92             =cut
93              
94             #----------------------------------------------------------------------------
95             #Constructors
96              
97             =head1 METHODS
98              
99             =head2 Constructor
100              
101             =head3 new ( [ CONFIGURATIONS ] )
102              
103             This is the constructor for a new C object.
104              
105             B
106              
107             =over 4
108              
109             =item C
110              
111             Key and value pairs containing the configurations.
112              
113             B
114              
115             C - The directory where the file is located.
116              
117             C - The base name of the file.
118              
119             C - The complete path with directory and file base name.
120              
121             =back
122              
123             See L|/"setFileDirectory ( DIRECTORY )">
124              
125             See L|/"setFileName ( NAME )">
126              
127             =cut
128              
129             sub new {
130              
131             #Take the Method Parameters
132 6     6 1 222460 my ( $invocant, %hshprms ) = @_;
133 6   33     56 my $class = ref($invocant) || $invocant;
134 6         12 my $self = undef;
135              
136             # Set the Default Attributes and assign the initial Values
137 6         111 $self = {
138             '_file' => undef,
139             '_directory_name' => '',
140             '_file_name' => '',
141              
142             # A Reference to the Content Text
143             '_file_content' => undef,
144             '_file_content_lines' => undef,
145             '_file_time' => -1,
146             '_file_access_time' => -1,
147             '_file_size' => -1,
148             '_package_size' => 32768,
149             '_buffered' => 0,
150             '_persistent' => 0,
151             '_locked' => 0,
152             '_writable' => 0,
153             '_appendable' => 0,
154             '_report' => '',
155             '_error_message' => '',
156             '_error_code' => 0
157             };
158              
159 6         13 bless $self, $class;
160              
161 6 100       25 if ( scalar( keys %hshprms ) > 0 ) {
162 5 100       22 $self->setFileDirectory( $hshprms{'filedirectory'} ) if ( defined $hshprms{'filedirectory'} );
163 5 100       21 $self->setFileName( $hshprms{'filename'} ) if ( defined $hshprms{'filename'} );
164 5 100       28 $self->setFilePath( $hshprms{'filepath'} ) if ( defined $hshprms{'filepath'} );
165             } #if(scalar(keys %hshprms) > 0)
166              
167             #Give the Object back
168 6         32 return $self;
169             }
170              
171             sub DESTROY {
172 6     6   9275 my $self = $_[0];
173              
174             # Free the System Resources
175 6         25 $self->freeResources;
176             }
177              
178             #----------------------------------------------------------------------------
179             #Administration Methods
180              
181             =head3 setFileDirectory ( DIRECTORY )
182              
183             This method sets the directory where the file is located.
184              
185             B
186              
187             =over 4
188              
189             =item C
190              
191             The directory where the file is located.
192              
193             If the directory does not end on a slash C< / > it will be appended.
194              
195             =back
196              
197             =cut
198              
199             sub setFileDirectory {
200 5     5 1 29 my $self = $_[0];
201              
202 5 50       21 if ( scalar(@_) > 1 ) {
203 5         16 $self->{'_directory_name'} = $_[1];
204             }
205             else #No Parameter given
206             {
207 0         0 $self->{'_directory_name'} = '';
208             }
209              
210 5 50       17 $self->{'_directory_name'} = '' unless ( defined $self->{'_directory_name'} );
211              
212 5 50       16 if ( $self->{'_directory_name'} ne '' ) {
213 5 100       52 $self->{'_directory_name'} .= '/' unless ( $self->{'_directory_name'} =~ qr#/$# );
214             }
215              
216             #Clear the File Object
217 5         27 $self->Clear;
218             }
219              
220             =head3 setFileName ( NAME )
221              
222             This method sets the base name of the file.
223              
224             B
225              
226             =over 4
227              
228             =item C
229              
230             The base name of the file.
231              
232             This will also close open file handles and free in-memory cache.
233              
234             =back
235              
236             See L|/"Clear ()">
237              
238             =cut
239              
240             sub setFileName {
241 5     5 1 9 my $self = $_[0];
242              
243 5 50       31 if ( scalar(@_) > 1 ) {
244 5         12 $self->{'_file_name'} = $_[1];
245             }
246             else #No Parameter given
247             {
248 0         0 $self->{'_file_name'} = '';
249             }
250              
251 5 50       16 $self->{'_file_name'} = '' unless ( defined $self->{'_file_name'} );
252              
253             # Clear the File Object
254 5         11 $self->Clear;
255             }
256              
257             =head3 setFilePath ( PATH )
258              
259             This method sets the complete path of the file.
260              
261             B
262              
263             =over 4
264              
265             =item C
266              
267             The complete path of the file.
268              
269             This will split the C and call C with the directory
270             and C with the file base name.
271              
272             =back
273              
274             See L|/"setFileDirectory ( DIRECTORY )">
275              
276             See L|/"setFileName ( NAME )">
277              
278             =cut
279              
280             sub setFilePath {
281 4     4 1 11 my $self = $_[0];
282 4   50     15 my $sdirnm = $_[1] || '';
283 4         7 my $sflnm = '';
284              
285 4 50       15 if ( $sdirnm ne '' ) {
286 4 50       14 if ( index( $sdirnm, '/' ) > -1 ) {
287 4 50       87 if ( $sdirnm =~ qr#(.*/)([^/]+)$# ) {
288 4         20 $sdirnm = $1;
289 4         12 $sflnm = $2;
290             }
291             }
292             else #The Path does not include a Slash Sign
293             {
294 0         0 $sflnm = $sdirnm;
295 0         0 $sdirnm = '';
296             }
297             }
298              
299             #Set the Parsed Values
300 4         22 $self->setFileDirectory($sdirnm);
301 4         15 $self->setFileName($sflnm);
302             }
303              
304             sub changeFileName {
305 0     0 0 0 my $self = $_[0];
306 0         0 my $sdirnm = '';
307 0   0     0 my $sflnm = $_[1] || '';
308 0         0 my $irs = 0;
309              
310 0 0       0 if ( $sflnm ne '' ) {
311              
312             #If File Name contains Directory Information
313 0 0       0 if ( index( $sflnm, '/' ) > -1 ) {
314 0 0       0 if ( $sflnm =~ qr#(.*/)([^/]+)$# ) {
315 0         0 $sdirnm = $1;
316 0         0 $sflnm = $2;
317             }
318             }
319              
320             #Assume the same Directory
321 0 0       0 $sdirnm = $self->{'_directory_name'}
322             if ( $sdirnm eq '' );
323              
324 0 0       0 if ( $self->Exists ) {
325 0         0 $irs = rename $self->{'_directory_name'} . $self->{'_file_name'}, $sdirnm . $sflnm;
326              
327 0 0       0 if ($irs) {
328              
329             #Update the File Access Object accordingly but keep the Report History
330              
331 0         0 $self->{'_directory_name'} = $sdirnm;
332 0         0 $self->{'_file_name'} = $sflnm;
333             }
334             else #Change File Name failed
335             {
336 0         0 $irs = 0 + $!;
337              
338             $self->{'_error_message'} .=
339             "File '"
340             . $self->{'_directory_name'}
341 0         0 . $self->{'_file_name'}
342             . "': Change File Name failed with [$irs]!"
343             . "Message: '$!'\n";
344 0 0       0 $self->{'_error_code'} = 1 if ( $self->{'_error_code'} < 1 );
345              
346 0         0 $irs = 0;
347             }
348             }
349             else #File does not exist
350             {
351 0         0 $self->{'_error_message'} .= "File does not exist!\n";
352 0 0       0 $self->{'_error_code'} = 3 if ( $self->{'_error_code'} < 1 );
353             }
354             }
355             else #New File Name was not given
356             {
357 0         0 $self->{'_error_message'} .= "New File Name is not set!\n";
358 0 0       0 $self->{'_error_code'} = 3 if ( $self->{'_error_code'} < 1 );
359             }
360              
361 0         0 return $irs;
362             }
363              
364             sub setContent {
365 3     3 0 6 my $self = $_[0];
366              
367 3         7 $self->{'_file_content'} = undef;
368 3         8 $self->{'_file_content_lines'} = undef;
369 3   100     19 $self->{'_buffered'} ||= 1;
370              
371 3 50       11 if ( scalar(@_) > 1 ) {
372 3 50       12 if ( ref( $_[1] ) eq '' ) {
373 3         7 $self->{'_file_content'} = \$_[1];
374             }
375             else {
376 0         0 $self->{'_file_content'} = $_[1];
377             }
378             }
379              
380 0         0 ${ $self->{'_file_content'} } = ''
381 3 50       11 unless ( defined $self->{'_file_content'} );
382              
383             }
384              
385             sub setContentArray {
386 1     1 0 2 my $self = $_[0];
387              
388 1         3 $self->{'_file_content'} = \'';
389 1         3 $self->{'_file_content_lines'} = undef;
390 1   50     4 $self->{'_buffered'} ||= 1;
391              
392 1 50       5 if ( scalar(@_) > 1 ) {
393 1 50       8 if ( ref( $_[1] ) eq '' ) {
394 0         0 $self->{'_file_content_lines'} = \$_[1];
395             }
396             else {
397 1         3 $self->{'_file_content_lines'} = $_[1];
398             }
399             }
400             }
401              
402             sub setFileTime {
403 0     0 0 0 my $self = $_[0];
404 0   0     0 my $itmfl = $_[1] || time;
405 0         0 my $irs = 0;
406              
407 0 0       0 if ( $self->Exists ) {
408 0         0 $self->getFileTime;
409              
410 0         0 $irs = utime $self->{'_file_access_time'}, $itmfl, $self->{'_directory_name'} . $self->{'_file_name'};
411              
412 0 0       0 if ( $irs < 1 ) {
413 0         0 $irs = 0 + $!;
414              
415             $self->{'_error_message'} .=
416             "File '"
417             . $self->{'_directory_name'}
418 0         0 . $self->{'_file_name'}
419             . "': Set File Time failed with [$irs]!"
420             . "Message: '$!'\n";
421 0 0       0 $self->{'_error_code'} = 1 if ( $self->{'_error_code'} < 1 );
422              
423 0         0 $irs = 0;
424             }
425             }
426             else #File does not exist
427             {
428 0         0 $self->{'_error_message'} .= "File does not exist!\n";
429 0 0       0 $self->{'_error_code'} = 3 if ( $self->{'_error_code'} < 1 );
430             }
431              
432 0         0 return $irs;
433             }
434              
435             sub setBuffered {
436 0     0 0 0 my $self = $_[0];
437              
438 0 0       0 if ( scalar(@_) > 1 ) {
439 0 0       0 if ( $_[1] =~ qr/^\d+$/ ) {
440              
441             # The parameter is an unsigned whole number
442              
443 0 0       0 if ( $_[1] != 0 ) {
444 0         0 $self->{'_buffered'} = 1;
445             }
446             else {
447 0         0 $self->{'_buffered'} = 0;
448             }
449             }
450             else #The Parameter is not a Number
451             {
452 0         0 $self->{'_buffered'} = 0;
453             }
454             }
455             else #No Parameter was given
456             {
457 0         0 $self->{'_buffered'} = 1;
458             }
459             }
460              
461             sub setPersistent {
462 0     0 0 0 my $self = $_[0];
463              
464 0 0       0 if ( scalar(@_) > 1 ) {
465 0 0       0 if ( $_[1] =~ qr/^\d+$/ ) {
466              
467             # The parameter is an unsigned whole number
468              
469 0 0       0 if ( $_[1] != 0 ) {
470 0         0 $self->{'_persistent'} = 1;
471             }
472             else {
473 0         0 $self->{'_persistent'} = 0;
474             }
475             }
476             else #The Parameter is not a Number
477             {
478 0         0 $self->{'_persistent'} = 0;
479             }
480             }
481             else #No Parameter was given
482             {
483 0         0 $self->{'_persistent'} = 1;
484             }
485             }
486              
487             =head3 Create ()
488              
489             This method will create an empty file.
490              
491             If the file already exists it will be truncated.
492              
493             =cut
494              
495             sub Create {
496 1     1 1 3 my $self = $_[0];
497              
498 1         6 return $self->writeContent('');
499             }
500              
501             sub _openrFile {
502 1     1   2 my $self = $_[0];
503 1         1 my $irs = 0;
504              
505 1 50       11 if ( $self->_isOpen() ) {
506              
507             #Reopen the File in shared Reading Mode
508 0 0       0 $self->_closeFile() if ( $self->_isWritable() );
509             } #if($self->_isOpen())
510              
511 1 50       3 unless ( $self->_isOpen() ) {
512 1 50       3 if ( $self->Exists() ) {
513              
514             #Open the File
515 1         59 $irs = open $self->{'_file'}, '<', $self->{'_directory_name'} . $self->{'_file_name'};
516              
517 1 50       6 if ( defined $irs ) {
518 1         13 $irs = flock( $self->{'_file'}, LOCK_SH );
519              
520 1 50       5 if ($irs) {
521 1         2 $self->{'_locked'} = 1;
522              
523 1         3 $irs = 1;
524             } #if($irs)
525             }
526             else #The File could not be opened
527             {
528             $self->{'_error_message'} .=
529             "File '"
530             . $self->{'_directory_name'}
531 0         0 . $self->{'_file_name'} . "': "
532             . "Open Read failed!\n"
533             . "Message: '$!'\n";
534 0 0       0 $self->{'_error_code'} = 1 if ( $self->{'_error_code'} < 1 );
535              
536 0         0 $irs = 0;
537             } #unless(defined $irs)
538             }
539             else #The File does not exist
540             {
541             $self->{'_error_message'} .=
542             "File '"
543             . $self->{'_directory_name'}
544 0         0 . $self->{'_file_name'} . "': "
545             . "Open Read failed!\n"
546             . "Message: 'File does not exist.'\n";
547 0 0       0 $self->{'_error_code'} = 3 if ( $self->{'_error_code'} < 1 );
548             }
549             }
550             else #The File is open and in Reading Mode
551             {
552 0         0 $irs = 1;
553             }
554              
555 1         3 return $irs;
556             }
557              
558             sub _openwFile {
559 4     4   7 my $self = $_[0];
560 4         7 my $irs = 0;
561              
562 4 50       10 unless ( $self->_isWritable() ) {
563 4 50       13 $self->_closeFile() if ( $self->_isOpen() );
564              
565 4 50       14 if ( $self->{'_directory_name'} ne '' ) {
566 4 100       120 unless ( -d $self->{'_directory_name'} ) {
567 1         3 my $idircnt = -1;
568              
569             $self->{"_report"} .=
570             "Directory '"
571 1         5 . $self->{'_directory_name'} . "': "
572             . "Directory does not exist. Directory creating ...\n";
573              
574             #Clear any previous Error Messages
575 1         2 $@ = '';
576              
577 1         3 eval {
578             #Create the Directory
579 1         390 $idircnt = make_path( $self->{'_directory_name'}, { mode => 0775 } );
580             };
581              
582 1 50       8 if ($@) {
583             $self->{'_error_message'} .=
584             "Directory '"
585 0         0 . $self->{'_directory_name'} . "': "
586             . "Create Directory failed.\n"
587             . "Message (Code '"
588             . ( $! + 0 )
589             . "'): '$@'\n";
590              
591 0 0       0 $self->{'_error_code'} = 1 if ( $self->{'_error_code'} < 1 );
592              
593 0         0 $idircnt = -1;
594             }
595              
596 1 50       5 $irs = 1 if ( $idircnt != -1 );
597             }
598             else # Directory does exist
599             {
600 3         11 $irs = 1;
601             }
602             }
603             else #The File Directory is not set
604             {
605 0         0 $irs = 1;
606             }
607              
608 4 50       13 if ($irs) {
609 4 50       16 if ( $self->{'_file_name'} ne '' ) {
610              
611             #Open the File
612 4         703 $irs = open $self->{'_file'}, ">", $self->{'_directory_name'} . $self->{'_file_name'};
613              
614 4 50       25 if ( defined $irs ) {
615 4         14 $self->{'_writable'} = 1;
616              
617 4         102 $irs = flock( $self->{'_file'}, LOCK_EX );
618              
619 4 50       18 if ($irs) {
620 4         12 $self->{'_locked'} = 1;
621              
622 4         12 $irs = 1;
623             }
624             }
625             else #The File could not be opened
626             {
627             $self->{'_error_message'} .=
628             "File '"
629             . $self->{'_directory_name'}
630 0         0 . $self->{'_file_name'}
631             . "': Open Write failed!\n"
632             . "Message: '$!'\n";
633 0 0       0 $self->{'_error_code'} = 1 if ( $self->{'_error_code'} < 1 );
634              
635 0         0 $irs = 0;
636             }
637             }
638             else #The File Name isnt set
639             {
640 0         0 $self->{'_error_message'} .= "File Name isn't set!\n";
641 0 0       0 $self->{'_error_code'} = 3 if ( $self->{'_error_code'} < 1 );
642              
643 0         0 $irs = 0;
644             }
645             }
646             }
647             else #The File is already open in Appending Mode
648             {
649 0         0 $irs = 1;
650             } #unless($self->_isWritable())
651              
652 4         13 return $irs;
653             }
654              
655             sub _openaFile {
656 0     0   0 my $self = $_[0];
657 0         0 my $irs = 0;
658              
659 0 0       0 unless ( $self->_isAppendable() ) {
660 0 0       0 $self->_closeFile() if ( $self->_isOpen() );
661              
662 0 0       0 if ( $self->{'_directory_name'} ne '' ) {
663 0 0       0 unless ( -d $self->{'_directory_name'} ) {
664 0         0 my $idircnt = -1;
665              
666             #Clear any previous Error Messages
667 0         0 $@ = '';
668              
669 0         0 eval {
670             #Create the Directory
671 0         0 $idircnt = make_path( $self->{'_directory_name'}, { mode => 0775 } );
672             };
673              
674 0 0       0 if ($@) {
675             $self->{'_error_message'} .=
676             "Directory '"
677 0         0 . $self->{'_directory_name'} . "': "
678             . "Create Directory failed.\n"
679             . "Message (Code '"
680             . ( 0 + $! )
681             . "'): '$@'\n";
682              
683 0 0       0 $self->{'_error_code'} = 1 if ( $self->{'_error_code'} < 1 );
684              
685 0         0 $idircnt = -1;
686             }
687              
688 0 0       0 $irs = 1 if ( $idircnt != -1 );
689             }
690             else # Directory does exist
691             {
692 0         0 $irs = 1;
693             }
694             }
695             else #The File Directory is not set
696             {
697 0         0 $irs = 1;
698             }
699              
700 0 0       0 if ($irs) {
701 0 0       0 if ( $self->{'_file_name'} ne '' ) {
702              
703             #Open the File
704 0         0 $irs = open $self->{'_file'}, ">>", $self->{'_directory_name'} . $self->{'_file_name'};
705              
706 0 0       0 if ( defined $irs ) {
707 0         0 $self->{'_writable'} = 1;
708 0         0 $self->{'_appendable'} = 1;
709              
710 0         0 $irs = flock( $self->{'_file'}, LOCK_EX );
711              
712 0 0       0 $irs = seek( $self->{'_file'}, 0, SEEK_END ) if ($irs);
713              
714 0 0       0 if ($irs) {
715 0         0 $self->{'_locked'} = 1;
716              
717 0         0 $irs = 1;
718             }
719             }
720             else #The File could not be opened
721             {
722             $self->{'_error_message'} .=
723             "File '"
724             . $self->{'_directory_name'}
725 0         0 . $self->{'_file_name'}
726             . "': Open Append failed!\n"
727             . "Message: '$!'\n";
728 0 0       0 $self->{'_error_code'} = 1 if ( $self->{'_error_code'} < 1 );
729              
730 0         0 $irs = 0;
731             }
732             }
733             else #The File Name isnt set
734             {
735 0         0 $self->{'_error_message'} .= "File Name isn't set!\n";
736 0 0       0 $self->{'_error_code'} = 3 if ( $self->{'_error_code'} < 1 );
737             }
738             }
739             }
740             else #The File is already open in Appending Mode
741             {
742 0         0 $irs = 1;
743             } #unless($self->_isAppendable())
744              
745 0         0 return $irs;
746             }
747              
748             sub Read {
749 1     1 0 3 my $self = $_[0];
750 1         2 my $irs = 0;
751              
752 1         3 ${ $self->{'_file_content'} } = '';
  1         3  
753 1         3 $self->{'_file_content_lines'} = undef;
754 1 50       5 $self->{'_buffered'} = 1 unless ( $self->{'_buffered'} );
755 1         2 $self->{'_file_time'} = -1;
756 1         3 $self->{'_file_size'} = -1;
757              
758 1 50       4 $self->_openrFile() if ( $self->_isWritable() );
759              
760 1 50       3 $self->_openrFile() unless ( $self->_isOpen() );
761              
762 1 50       3 if ( $self->_isOpen() ) {
763 1         2 my $scntntln = '';
764 1         3 my $irdcnt = -1;
765              
766             do #while($irdcnt);
767 1         2 {
768 2         54 $irdcnt = sysread( $self->{'_file'}, $scntntln, $self->{"_package_size"} );
769              
770 2 50       9 if ( defined $irdcnt ) {
771 2 100       6 ${ $self->{'_file_content'} } .= $scntntln if ( $irdcnt > 0 );
  1         7  
772             }
773             else #An Error has ocurred
774             {
775             $self->{'_error_message'} .=
776             "File '"
777             . $self->{'_directory_name'}
778 0         0 . $self->{'_file_name'}
779             . "': Read File failed with ["
780             . ( 0 + $! ) . "]!!"
781             . "Message: '$!'\n";
782 0 0       0 $self->{'_error_code'} = 1 if ( $self->{'_error_code'} < 1 );
783             }
784             } while ($irdcnt);
785              
786 1 50       6 $irs = 1 unless ($!);
787              
788 1 50       4 if ($irs) {
789 1         14 my @arrflstt = stat( $self->{'_file'} );
790              
791 1 50       4 if ( scalar(@arrflstt) > 0 ) {
792 1         2 $self->{'_file_time'} = $arrflstt[9];
793 1         3 $self->{'_file_size'} = $arrflstt[7];
794             }
795             else #The File Attributes are empty
796             {
797             $self->{'_error_message'} .=
798 0         0 "File '" . $self->{'_directory_name'} . $self->{'_file_name'} . "': File Attributes failed!\n";
799             }
800             }
801              
802 1 50       4 if ( $self->{'_persistent'} ) {
803 0 0       0 unless ($irs) {
804             $self->{'_error_message'} .=
805             "File '"
806             . $self->{'_directory_name'}
807 0         0 . $self->{'_file_name'} . "': "
808             . "File closing because of Reading Error ...\n";
809              
810             #Close the File
811 0         0 $self->_closeFile();
812             }
813             }
814             else #File is not persistent
815             {
816             #Close the File
817 1         6 $self->_closeFile();
818             }
819             }
820              
821 1         8 return $irs;
822             }
823              
824             sub readContent {
825 0     0 0 0 my $self = $_[0];
826              
827 0         0 $self->Read();
828              
829 0         0 return $self->getContent;
830             }
831              
832             sub readContentArray {
833 0     0 0 0 my $self = $_[0];
834              
835 0         0 File::Access::Driver::Read $self;
836              
837 0         0 return $self->getContentArray;
838             }
839              
840             =head3 Truncate ()
841              
842             This method will empty an existing file.
843              
844             If the file does not exist it will be created.
845              
846             =cut
847              
848             sub Truncate {
849 1     1 1 3 my $self = $_[0];
850              
851 1         6 return $self->writeContent('');
852             }
853              
854             sub Write {
855 4     4 0 8 my $self = $_[0];
856 4         7 my $irs = 0;
857              
858 4 50       12 $self->{'_buffered'} = 1 unless ( $self->{'_buffered'} );
859 4         34 $self->{'_file_time'} = -1;
860 4         10 $self->{'_file_access_time'} = -1;
861 4         9 $self->{'_file_size'} = -1;
862              
863 4 50       15 unless ( $self->_isWritable() ) {
864 4 50       8 $self->_closeFile() if ( $self->_isOpen() );
865              
866             #Open the File in Write Mode
867 4         14 $self->_openwFile();
868             }
869              
870 4 50       15 if ( $self->_isWritable() ) {
871 4         8 my $iwrtcnt = -1;
872 4         15 my $content = $self->getContent();
873 4         7 my $icntntlen = length( ${$content} );
  4         7  
874              
875 4         6 $irs = 0;
876              
877             # Write the Content Line to the File
878 4         10 $iwrtcnt = syswrite( $self->{'_file'}, ${$content} );
  4         103  
879              
880 4 50       17 if ( defined $iwrtcnt ) {
881 4         7 $irs = 1;
882              
883 4 50       12 if ( $iwrtcnt != $icntntlen ) {
884             $self->{'_error_message'} .=
885             "File '"
886             . $self->{'_directory_name'}
887 0         0 . $self->{'_file_name'}
888             . "': '$iwrtcnt' from '$icntntlen' Bytes written.\n";
889             }
890             }
891             else # An Error has ocurred
892             {
893             $self->{'_error_message'} .=
894             "File '"
895             . $self->{'_directory_name'}
896 0         0 . $self->{'_file_name'}
897             . "': File Write failed!\n"
898             . "Message: '$!'\n";
899 0 0       0 $self->{'_error_code'} = 1 if ( $self->{'_error_code'} < 1 );
900             }
901              
902 4 50       11 if ($irs) {
903 4         63 my @arrflstt = stat( $self->{'_file'} );
904              
905 4 50       14 if ( scalar(@arrflstt) > 0 ) {
906 4         8 $self->{'_file_time'} = $arrflstt[9];
907 4         9 $self->{'_file_access_time'} = $arrflstt[8];
908 4         12 $self->{'_file_size'} = $arrflstt[7];
909             }
910             else #The File Attributes are empty
911             {
912             $self->{'_error_message'} .=
913 0         0 "File '" . $self->{'_directory_name'} . $self->{'_file_name'} . "': File Attributes failed!\n";
914             }
915             }
916              
917 4 50       10 if ( $self->{'_persistent'} ) {
918 0 0       0 unless ($irs) {
919             $self->{'_error_message'} .=
920             "File '"
921             . $self->{'_directory_name'}
922 0         0 . $self->{'_file_name'} . "': "
923             . "File closing because of Writing Error ...\n";
924              
925             #Close the File
926 0         0 $self->_closeFile();
927             }
928             }
929             else #File is not persistent
930             {
931             #Close the File
932 4         16 $self->_closeFile();
933             }
934             }
935              
936 4         46 return $irs;
937             }
938              
939             sub writeContent {
940 3     3 0 8 my $self = $_[0];
941              
942 3         15 $self->setContent( $_[1] );
943              
944 3         9 return File::Access::Driver::Write $self;
945             }
946              
947             sub appendLine {
948 0     0 0 0 my $self = $_[0];
949 0         0 my $rcntntln = undef;
950 0         0 my $irs = 0;
951              
952 0         0 $self->{'_file_time'} = -1;
953 0         0 $self->{'_file_size'} = -1;
954              
955 0 0       0 if ( scalar(@_) > 1 ) {
956 0 0       0 if ( ref( $_[1] ) ne '' ) {
957 0         0 $rcntntln = $_[1];
958             }
959             else {
960 0         0 $rcntntln = \$_[1];
961             }
962              
963 0 0       0 if ( $$rcntntln ne '' ) {
964 0 0       0 if ( $self->{'_buffered'} > 0 ) {
965 0         0 ${ $self->{'_file_content'} } .= $$rcntntln;
  0         0  
966             }
967             }
968             }
969              
970 0 0       0 unless ( $self->_isAppendable() ) {
971 0 0       0 $self->_closeFile() if ( $self->_isOpen() );
972              
973             #Open the File in Appending Mode
974 0         0 $self->_openaFile();
975             }
976              
977 0 0       0 if ( $self->_isAppendable() ) {
978 0         0 my $iwrtcnt = -1;
979 0         0 my $icntntlen = length($$rcntntln);
980              
981 0         0 $irs = 0;
982              
983             #Write the Content Line to the File
984 0         0 $iwrtcnt = syswrite( $self->{'_file'}, $$rcntntln );
985              
986 0 0       0 if ( defined $iwrtcnt ) {
987 0         0 $irs = 1;
988              
989 0 0       0 if ( $iwrtcnt != $icntntlen ) {
990             $self->{'_error_message'} .=
991             "File '"
992             . $self->{'_directory_name'}
993 0         0 . $self->{'_file_name'} . "': "
994             . "'$iwrtcnt' from '$icntntlen' Bytes written.\n";
995             }
996             }
997             else #An Error has ocurred
998             {
999             $self->{'_error_message'} .=
1000             "File '"
1001             . $self->{'_directory_name'}
1002 0         0 . $self->{'_file_name'}
1003             . "': File Write failed!\n"
1004             . "Message: '$!'\n";
1005 0 0       0 $self->{'_error_code'} = 1 if ( $self->{'_error_code'} < 1 );
1006             }
1007              
1008 0 0       0 if ($irs) {
1009 0         0 my @arrflstt = stat( $self->{'_file'} );
1010              
1011 0 0       0 if ( scalar(@arrflstt) > 0 ) {
1012 0         0 $self->{'_file_time'} = $arrflstt[9];
1013 0         0 $self->{'_file_size'} = $arrflstt[7];
1014             }
1015             else #The File Attributes are empty
1016             {
1017             $self->{'_error_message'} .=
1018 0         0 "File '" . $self->{'_directory_name'} . $self->{'_file_name'} . "': File Attributes failed!\n";
1019             }
1020             }
1021              
1022 0 0       0 if ( $self->{'_persistent'} > 0 ) {
1023 0 0       0 unless ( $irs > 0 ) {
1024             $self->{'_error_message'} .=
1025             "File '"
1026             . $self->{'_directory_name'}
1027 0         0 . $self->{'_file_name'} . "': "
1028             . "File closing because of Writing Error ...\n";
1029              
1030             #Close the File
1031 0         0 $self->_closeFile();
1032             }
1033             }
1034             else #File is not persistent
1035             {
1036             #Close the File
1037 0         0 $self->_closeFile();
1038             }
1039             } #if($self->_isAppendable())
1040              
1041 0         0 return $irs;
1042             }
1043              
1044             sub writeLine {
1045 0     0 0 0 my $self = $_[0];
1046              
1047 0         0 return $self->appendLine( $_[1] );
1048             }
1049              
1050             sub Delete {
1051 4     4 0 18 my $self = $_[0];
1052 4         8 my $irs = 0;
1053              
1054             #Close the Open File
1055 4 50       12 $self->_closeFile() if ( $self->_isOpen );
1056              
1057 4 100       14 if ( $self->Exists ) {
1058 2         248 $irs = unlink $self->{'_directory_name'} . $self->{'_file_name'};
1059              
1060 2 50       21 if ( $irs < 1 ) {
1061             $self->{'_error_message'} .=
1062             "File '"
1063             . $self->{'_directory_name'}
1064 0         0 . $self->{'_file_name'}
1065             . "': Delete File failed with ["
1066             . ( 0 + $! ) . "]!"
1067             . "Message: '$!'\n";
1068 0 0       0 $self->{'_error_code'} = 1 if ( $self->{'_error_code'} < 1 );
1069              
1070 0         0 $irs = 0;
1071             }
1072             }
1073             else #The File does not exist
1074             {
1075 2         5 $irs = 1;
1076             }
1077              
1078 4         51 return $irs;
1079             }
1080              
1081             sub _closeFile {
1082 5     5   8 my $self = $_[0];
1083 5         8 my $irs = 0;
1084              
1085 5 50       15 if ( $self->_isOpen() ) {
1086 5 50       36 if ( $self->{'_locked'} > 0 ) {
1087 5         52 $irs = flock( $self->{'_file'}, LOCK_UN );
1088              
1089 5 50       11 unless ($irs) {
1090             $self->{'_error_message'} .=
1091             "File '"
1092             . $self->{'_directory_name'}
1093 0         0 . $self->{'_file_name'} . "': "
1094             . "Lock Release failed!\n"
1095             . "Message: '$!'\n";
1096 0 0       0 $self->{'_error_code'} = 1 if ( $self->{'_error_code'} < 1 );
1097             }
1098             else #File Lock was released
1099             {
1100 5         31 $self->{'_locked'} = 0;
1101             }
1102             }
1103              
1104 5         88 $irs = close $self->{'_file'};
1105              
1106 5 50       16 unless ( $irs > 0 ) {
1107             $self->{'_error_message'} .=
1108             "File '"
1109             . $self->{'_directory_name'}
1110 0         0 . $self->{'_file_name'} . "': "
1111             . "Close failed!\n"
1112             . "Message: '$!'\n";
1113 0 0       0 $self->{'_error_code'} = 1 if ( $self->{'_error_code'} < 1 );
1114             } #unless($irs > 0)
1115              
1116 5         27 $self->{'_file'} = undef;
1117 5         10 $self->{'_writable'} = 0;
1118 5         10 $self->{'_appendable'} = 0;
1119              
1120             #To Refresh on next Request
1121 5         8 $self->{'_file_access_time'} = -1;
1122 5         9 $self->{'_file_time'} = -1;
1123 5         11 $self->{'_file_size'} = -1;
1124              
1125             }
1126             else #The File is not open
1127             {
1128 0         0 $irs = 1;
1129             }
1130              
1131 5         14 return $irs;
1132             }
1133              
1134             =head3 Clear ()
1135              
1136             This method closed the file handle and frees the in-memory cache
1137             and resets also the in-memory file attributes.
1138              
1139             =cut
1140              
1141             sub Clear {
1142 10     10 1 19 my $self = $_[0];
1143              
1144             #Close the Open File
1145 10 50       28 $self->_closeFile() if ( $self->_isOpen() );
1146              
1147             #Clear Content
1148 10         21 $self->{'_file_content'} = undef;
1149 10         17 $self->{'_file_content_lines'} = undef;
1150              
1151 10         29 $self->clearErrors;
1152              
1153             #To Refresh on next Request
1154 10         17 $self->{'_file_access_time'} = -1;
1155 10         16 $self->{'_file_time'} = -1;
1156 10         17 $self->{'_file_size'} = -1;
1157              
1158             }
1159              
1160             =head3 clearErrors ()
1161              
1162             Clear the error and activity report and reset the error code.
1163              
1164             =cut
1165              
1166             sub clearErrors {
1167 11     11 1 18 my $self = $_[0];
1168              
1169 11         18 $self->{"_report"} = '';
1170 11         17 $self->{'_error_message'} = '';
1171 11         20 $self->{'_error_code'} = 0;
1172             }
1173              
1174             =head3 freeResources ()
1175              
1176             This method closed the file handle and frees the in-memory cache.
1177              
1178             =cut
1179              
1180             sub freeResources {
1181 6     6 1 10 my $self = $_[0];
1182              
1183 6 50       22 if ( $self->_isOpen ) {
1184              
1185             # Close the Open File
1186 0         0 $self->_closeFile();
1187             }
1188              
1189             #Clear Content
1190 6         14 $self->{'_file_content'} = undef;
1191 6         211 $self->{'_file_content_lines'} = undef;
1192             }
1193              
1194             #----------------------------------------------------------------------------
1195             #Consultation Methods
1196              
1197             sub getFileDirectory {
1198 3     3 0 16 return $_[0]->{'_directory_name'};
1199             }
1200              
1201             sub getFileName {
1202 14     14 0 3400 return $_[0]->{'_file_name'};
1203             }
1204              
1205             sub getFilePath {
1206 3     3 0 21 return $_[0]->{'_directory_name'} . $_[0]->{'_file_name'};
1207             }
1208              
1209             sub getContent {
1210 5     5 0 10 my $self = $_[0];
1211              
1212             $self->{'_file_content'} = \''
1213 5 50       18 unless ( defined $self->{'_file_content'} );
1214              
1215 5 100       8 if ( ${ $self->{'_file_content'} } eq '' ) {
  5         20  
1216 3 100       6 if ( scalar( @{ $self->{'_file_content_lines'} } ) > 0 ) {
  3         11  
1217 1         3 my $content = join( "\n", @{ $self->{'_file_content_lines'} } );
  1         5  
1218              
1219 1         3 $self->{'_file_content'} = \$content;
1220             }
1221             }
1222              
1223 5         11 return $self->{'_file_content'};
1224             }
1225              
1226             sub getContentArray {
1227 1     1 0 2140 my $self = $_[0];
1228              
1229 1         3 @{ $self->{'_file_content_lines'} } = ()
1230 1 50       6 unless ( defined $self->{'_file_content_lines'} );
1231              
1232 1 50       2 if ( scalar( @{ $self->{'_file_content_lines'} } ) == 0 ) {
  1         5  
1233 1 50       2 if ( ${ $self->{'_file_content'} } ne '' ) {
  1         4  
1234 1         1 @{ $self->{'_file_content_lines'} } = split( "\n", ${ $self->{'_file_content'} } );
  1         4  
  1         6  
1235             }
1236             }
1237              
1238 1         4 return $self->{'_file_content_lines'};
1239             }
1240              
1241             sub getFileTime {
1242 0     0 0 0 my $self = $_[0];
1243              
1244 0 0       0 if ( $self->Exists() ) {
1245 0 0       0 if ( $self->{'_file_time'} < 0 ) {
1246 0         0 my @arrflstt = stat( $self->{'_directory_name'} . $self->{'_file_name'} );
1247              
1248 0         0 $self->{'_file_time'} = -1;
1249 0         0 $self->{'_file_access_time'} = -1;
1250 0         0 $self->{'_file_size'} = -1;
1251              
1252 0 0       0 if ( scalar(@arrflstt) > 0 ) {
1253 0         0 $self->{'_file_time'} = $arrflstt[9];
1254 0         0 $self->{'_file_access_time'} = $arrflstt[8];
1255 0         0 $self->{'_file_size'} = $arrflstt[7];
1256             }
1257             else #The File Attributes are empty
1258             {
1259             $self->{'_error_message'} .=
1260 0         0 "File '" . $self->{'_directory_name'} . $self->{'_file_name'} . "': File Attributes failed!\n";
1261 0 0       0 $self->{'_error_code'} = 1 if ( $self->{'_error_code'} < 1 );
1262             }
1263             }
1264             }
1265             else #The File does not exist
1266             {
1267 0         0 $self->{'_file_time'} = -1;
1268 0         0 $self->{'_file_access_time'} = -1;
1269 0         0 $self->{'_file_size'} = -1;
1270             }
1271              
1272 0         0 return $self->{'_file_time'};
1273             }
1274              
1275             sub getFileSize {
1276 5     5 0 14 my $self = $_[0];
1277              
1278 5 50       16 if ( $self->Exists() ) {
1279 5 50       21 if ( $self->{'_file_size'} < 0 ) {
1280 5         108 my @arrflstt = stat( $self->{'_directory_name'} . $self->{'_file_name'} );
1281              
1282 5         15 $self->{'_file_time'} = -1;
1283 5         14 $self->{'_file_access_time'} = -1;
1284 5         9 $self->{'_file_size'} = -1;
1285              
1286 5 50       35 if ( scalar(@arrflstt) > 0 ) {
1287 5         11 $self->{'_file_time'} = $arrflstt[9];
1288 5         9 $self->{'_file_access_time'} = $arrflstt[8];
1289 5         15 $self->{'_file_size'} = $arrflstt[7];
1290             }
1291             else #The File Attributes are empty
1292             {
1293             $self->{'_error_message'} .=
1294 0         0 "File '" . $self->{'_directory_name'} . $self->{'_file_name'} . "': File Attributes failed!\n";
1295 0 0       0 $self->{'_error_code'} = 1 if ( $self->{'_error_code'} < 1 );
1296             }
1297             }
1298             }
1299             else #The File does not exist
1300             {
1301 0         0 $self->{'_file_time'} = -1;
1302 0         0 $self->{'_file_access_time'} = -1;
1303 0         0 $self->{'_file_size'} = -1;
1304             }
1305              
1306 5         36 return $self->{'_file_size'};
1307             }
1308              
1309             sub Exists {
1310 17     17 0 31 my $self = $_[0];
1311 17         23 my $irs = 0;
1312              
1313 17 50       37 unless ( $self->_isOpen() ) {
1314 17 50       46 if ( $self->{'_file_name'} ne '' ) {
1315 17 50       32 if ( $self->{'_directory_name'} ne '' ) {
1316 17 100       651 $irs = 1 if ( -d $self->{'_directory_name'} );
1317             }
1318             else #The Directory Name isnt set
1319             {
1320 0         0 $irs = 1;
1321             }
1322              
1323 17 100       52 if ($irs) {
1324 15 100       320 $irs = 0 unless ( -e $self->{'_directory_name'} . $self->{'_file_name'} );
1325             }
1326             }
1327             else #The File Name isnt set
1328             {
1329 0         0 $self->{'_error_message'} .= "File Name isn't set!\n";
1330 0 0       0 $self->{'_error_code'} = 3 if ( $self->{'_error_code'} < 1 );
1331             }
1332             }
1333             else #The File is already open
1334             {
1335 0         0 $irs = 1;
1336             }
1337              
1338 17         90 return $irs;
1339             }
1340              
1341             sub _isOpen {
1342 67     67   82 my $self = $_[0];
1343 67         84 my $iopn = 0;
1344              
1345 67 100       132 if ( defined $self->{'_file'} ) {
1346 10 50       64 $iopn = 1 if ( fileno( $self->{'_file'} ) );
1347             }
1348             else #The File Handle is not set
1349             {
1350 57 50       109 $self->{'_file'} = undef unless ( exists $self->{'_file'} );
1351             }
1352              
1353 67         171 return $iopn;
1354             }
1355              
1356             sub _isWritable {
1357 13     13   21 my $self = $_[0];
1358 13         19 my $iopn = 0;
1359              
1360 13 100       27 if ( $self->_isOpen() ) {
1361 4 50       13 $iopn = $self->{'_writable'} if ( defined $self->{'_writable'} );
1362             }
1363              
1364 13         37 return $iopn;
1365             }
1366              
1367             sub _isAppendable {
1368 0     0   0 my $self = $_[0];
1369 0         0 my $iopn = 0;
1370              
1371 0 0       0 if ( $self->_isOpen() ) {
1372 0 0       0 $iopn = $self->{'_appendable'} if ( defined $self->{'_appendable'} );
1373             }
1374              
1375 0         0 return $iopn;
1376             }
1377              
1378             sub isBuffered {
1379 0     0 0 0 return $_[0]->{'_buffered'};
1380             }
1381              
1382             sub isPersistent {
1383 0     0 0 0 return $_[0]->{'_persistent'};
1384             }
1385              
1386             sub getReportString {
1387 3     3 0 38 return \$_[0]->{"_report"};
1388             }
1389              
1390             sub getErrorString {
1391 6     6 0 49 return \$_[0]->{'_error_message'};
1392             }
1393              
1394             sub getErrorCode {
1395 6     6 0 153 return $_[0]->{'_error_code'};
1396             }
1397              
1398             return 1;