package Ernad::Files; use strict; use warnings; use Carp qw(confess); use Cwd 'abs_path'; use Data::Dumper; use File::Basename; use File::Copy; use File::Compare; use File::Path; use File::Temp qw/ tempfile tempdir /; use File::Slurper; use File::Slurp; use IO::Compress::Gzip qw(gzip $GzipError); use Ernad::Constant; use Krichel::File; sub exist { my $glob=shift // confess "I need a glob here."; my @globs = glob($glob); if( scalar( @globs ) > 0 ) { return 1; } return 0; } sub get_abs_path { my $file=shift or return ''; my $abs_path; #if( -f $file && -l $file ) { $abs_path=abs_path($file); #} #print "abs_path is $abs_path\n"; return $abs_path; } sub save_xml_with_temp { my $dest_file=shift; my $doc=shift; my ($fh, $temp_file) = tempfile(); #print $doc->toString; $doc->toFile($temp_file,2); if(not -f $dest_file or compare($dest_file,$temp_file)) { copy($temp_file,$dest_file); return 1; } unlink $temp_file; return 0; } ## new function, saves both text and xml sub save_if_diff { my $file=shift; my $in=shift; my $ref_in=ref($in); if($ref_in eq 'XML::LibXML::Document') { my $has_saved=&save_xml_with_temp($file,$in); return $has_saved; } if(not $ref_in) { my $has_saved=&save_text_with_temp($file,$in); return $has_saved; } confess "I can't deal with your input of time $ref_in."; } sub save_text_with_temp { my $dest_file=shift; my $txt=shift; my ($fh, $temp_file) = tempfile(); &File::Slurper::write_text($temp_file,$txt); my $status=0; if(not -f $dest_file or compare($dest_file,$temp_file)) { copy($temp_file,$dest_file); $status=1; } unlink $temp_file; return $status; } sub write_doc { my $arg_1=shift // confess "I need two arguments here"; my $arg_2=shift // confess "I need two arguments here"; my $ref_1=ref $arg_1; my $ref_2=ref $arg_2; my $file; my $doc; if($ref_1 eq 'XML::LibXML::Document' and not $ref_2) { $file=$arg_2; $doc=$arg_1; } elsif($ref_2 eq 'XML::LibXML::Document' and not $ref_2) { $file=$arg_1; $doc=$arg_2; } if(not -f $file) { if(substr($file,-3) eq '.gz') { $file=substr($file,0,length($file)-3); $doc->toFile($file); system("/bin/gzip $file"); return "$file.gz"; } $doc->toFile($file); return $file; } my $status=0; my ($fh, $temp_file) = tempfile(); $doc->toFile($temp_file); if(substr($file,-3) eq '.gz') { system("/bin/gzip $temp_file"); $temp_file.='.gz'; } if(compare($file,$temp_file)) { copy($temp_file,$file); $status=1; } unlink $temp_file; return $status; } sub write_string { my $file=shift // confess "I need a file here"; &Krichel::File::prepare($file); my $txt=shift // confess "I need a string here."; if(ref($txt)) { confess "I need as string, not an object."; } if(not $txt) { confess "I don't write an empty string to a file."; } if($file=~m|\.gz$|) { my $fh; $fh = IO::Compress::Gzip->new($file) or confess "I not write to $file: $GzipError"; $fh->print($txt); $fh->close(); return 1; } &File::Slurp::write_file($file,$txt); return 1; } sub read_string { my $file=shift; my $txt; if($file=~m|\.gz$|) { my $input = new IO::File "< $file" or confess "I can not open '$file': $!" ; gzip $input => \$txt or confess "I could not read the compressid file $file $GzipError\n"; return $txt; } $txt=&File::Slurp::read_file($file); return $txt; } ## seems wrong because it does not account for gz sub save_xml_with_temp_and_time { my $dest_file=shift; my $doc=shift; my ($fh, $temp_file) = tempfile(); $doc->toFile($temp_file,2); my $dir=dirname($dest_file); if(not -d $dir) { mkpath $dir; copy($temp_file,$dest_file); unlink $temp_file; return 1; } my $bana=basename($dest_file); $bana=~m|([^.]+)\.(.*)|; my $main=$1; my $ext=$2; ## old way to do time if($main=~m|(.*_)\d{10}$|) { my $b4digit=$1; my $search="$dir/$b4digit*.$ext"; my @allready_there_files=glob($search); if(scalar @allready_there_files) { foreach my $candidate (@allready_there_files) { if(compare($candidate,$temp_file)==0) { ## a copy of this is already there #print "found an eearlier copy $candidate\n"; return 0; } } } } ## new way to do time if($main=~m|(.*_)[0-9a-z]{6}$|) { my $b4digit=$1; my $search="$dir/$b4digit*.$ext"; my @allready_there_files=glob($search); if(scalar @allready_there_files) { foreach my $candidate (@allready_there_files) { if(compare($candidate,$temp_file)==0) { ## a copy of this is already there #print "found an eearlier copy $candidate\n"; return 0; } } } } copy($temp_file,$dest_file); unlink $temp_file; return 1; } ## fixme prepare should be an alias and all references ## to prepare_for_file should be changed #sub prepare { # my $file=shift // ''; # if(not $file) { # confess "I need a file here."; # } # my $dir=dirname($file); # if(-d $dir) { # return; # } # #print "Trying to make $dir\n"; # my $target=readlink($dir) // ''; # #print "target is $target\n"; # if($target) { # mkpath($target); # return; # } # #print "directory $dir is not a link\n"; # #print `ls $dir`; # if(not -d $dir) { # unlink $dir; # mkpath($dir); # } #} # # sub prepare_for_file { # my $file=shift // ''; # if(not $file) { # confess "I need a file here."; # } # my $dir=dirname($file); # if(-d $dir) { # return; # } # #print "Trying to make $dir\n"; # my $target=readlink($dir) // ''; # #print "target is $target\n"; # if($target) { # mkpath($target); # return; # } # #print "directory $dir is not a link\n"; # #print `ls $dir`; # if(not -d $dir) { # unlink $dir; # mkpath($dir); # } # } sub xml_to_html { my $xml_file=shift; my $dir=shift // ''; my $xml_bana=basename($xml_file); my $html_bana=substr($xml_bana,0,length($xml_bana)-4); my $html_fufi="$dir/$html_bana.html"; return $html_fufi; } sub is_emacs_file { my $file=shift; ## emacs backups if($file=~m|~|) { return 1; } ## emacs autosaves my $bana=basename($file); if($bana=~m|^#| and $bana=~m|#$|) { return 1; } } sub check_link { my $in_link=shift; my $verbose=0; if(not -l $in_link) { return; } my $dir=&dirname($in_link); if($verbose) { print "in_link is $in_link\n"; } my $target=$dir.'/'.readlink $in_link; if($verbose) { print "target is $target\n"; } if(not -f $target) { warn "broken link $in_link"; system("rm $in_link"); } } sub remove_dangling_opt_link_to_file { my $in=shift; my $verbose=0; if(-f $in) { return; } if(-l $in) { return; } my $no_opt_out_file=Ernad::Files::remove_opt($in); if(-l $no_opt_out_file) { &Ernad::Files::check_link($no_opt_out_file); if($verbose) { print "I delete the link $no_opt_out_file\n"; } system("rm $no_opt_out_file"); } } sub check_links_in_dir { my $dir=shift or die; my $verbose=0; if(not -d $dir) { die "no such directory '$dir'"; } my $file; my $dh; opendir(DH, $dir); while ($file = readdir DH ) { if(not -l $file) { next; } if($verbose) { print "$file\n"; } my $link="$dir/$file"; &check_link($link); } } sub remove_opt { my $in=shift; my $opt=$Ernad::Constant::c->{'opt_dir'}; my $no_opt=$in; $no_opt=~s|(.*)/$opt/(.*)|$1/$2|; if(not $in=~m|/$opt/|) { return ''; } return $no_opt; } sub make_opt_link { my $in=shift; my $no_opt=$in; my $verbose=0; my $opt=$Ernad::Constant::c->{'opt_dir'}; if(not $in=~m|/$opt/|) { return; } $no_opt=~s|(.*)/$opt/(.*)|$1/$2|; my $before_opt=$1; my $after_opt=$2; if(-f $no_opt and not -l $no_opt) { if($verbose) { print "an extra non-opt file $no_opt is there\n"; } return; } if(-f $no_opt) { if($verbose) { print "file $no_opt is there\n"; } return; } if(-r $no_opt) { if($verbose) { print "link $no_opt is there\n"; } return; } my $sys="cd $before_opt; ln -s $opt/$after_opt $after_opt"; if($verbose) { print "running '$sys'\n"; } system($sys); } sub check_text_link { my $in_file=shift; my $out_dir=shift; my $verbose=0; my $in_dir=dirname($in_file); my $fina=basename($in_file); my $out_file="$out_dir/$fina"; if(-l "$in_file.txt" and not -l "$out_file.txt") { unlink "$out_file.txt"; my $out_fina=basename($out_file); my $s="cd $out_dir; ln -s $fina $fina.txt"; if($verbose) { print "linking $s\n"; } system($s); } } sub does_file_need_renewal { my $in_file=shift; my @others=@_; my $verbose=0; my $now=time; if(not -f $in_file) { if($verbose) { print "file $in_file is not there, it needs renewing.\n"; } return $now; } if($verbose) { print "file $in_file is there ... "; } if(-z $in_file) { if($verbose) { print "file $in_file is empty, it needs renewing.\n"; } return time; } ## -M Script start time minus file modification time, in days. my $target_time=-M $in_file; if($verbose) { print "target_time is $target_time\n"; } if($verbose) { print Dumper @others; } my $min_ago=time; foreach my $file (@others) { if($verbose) { print "considering $file as renewal target\n"; } if(not $file) { confess "I don't have the file $file"; } if(-d $file) { ## directory case, not treated recursively my $dirname=$file; opendir( my $dir, $dirname ) or die "Error: can't open dir $dirname"; my $file; while ($file = readdir $dir ) { ## skipping "." and ".." if ( ($file eq "." ) or ( $file eq ".." )) { next; } $file="$dirname/$file"; if(not -M $file) { die "can not find time on file $file"; } my $ago=-M $file; if($ago < $min_ago) { $min_ago=$ago; } } ## finished with this next; } if(not -f $file) { confess "I can not find the file '$file'"; } #if(not -M $file) { # confess "I can not find the time on file '$file'"; #} my $ago=-M $file; if($verbose) { print "time on file $file is $ago\n"; } if($ago < $min_ago) { $min_ago=$ago; } } if($min_ago < $target_time) { if($verbose) { print " but $in_file is newer, renewal required\n"; } my $time=time()+$min_ago; return $time; } if($verbose) { print " no reed to renew $in_file\n"; } return 0; } sub check_opt_links { my $web_opt_dir=shift; my $verbose=0; foreach my $file (`find $web_opt_dir`) { chomp $file; if(not $file) { next; } my $no_opt=&Ernad::Files::remove_opt($file); if(not $no_opt) { if($verbose) { print "found no no_opt file\n"; } next; } if(-l $no_opt) { if($verbose) { print "$no_opt link is there.\n"; } next; } if(&Ernad::Files::get_abs_path($no_opt) eq $file) { if($verbose) { print "$no_opt is the same as $file\n"; } next; } if(-d $no_opt) { next; } print "no_opt '$no_opt'\n"; &make_opt_link($file,$no_opt); } } ## sub mtime { my $file=shift // confess "I need a file here."; if(not -f $file) { confess "I can't see the file $file"; } my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size, $atime,$mtime,$ctime,$blksize,$blocks) = stat($file); return $mtime; } ### sub count_amf_files_in_dir { my $dir=shift; opendir(DH, $dir) or confess "I can't open the directory $dir"; my $ext=$Ernad::Constant::c->{'amf_ext'}; my $count=0; my $file; my $debug=0; while ($file = readdir DH ) { if($debug) { print "I look at file $file, looking for $ext.\n"; } if($file=~m|\Q$ext\E$|) { if($debug) { print "found file $file\n"; } $count++; } } return $count; } 1;