#!/usr/bin/perl use strict; use warnings; my($app_svnid) = '$HeadURL$ $LastChangedRevision$'; ## no critic (RequireInterpolationOfMetachars) use lib substr(`ade-config ade_share_prefix`,0,-1) . '/include'; ## no critic (ProhibitBacktickOperators) use ADE; use lib substr(`fad-config fad_share_prefix`,0,-1) . '/include'; ## no critic (ProhibitBacktickOperators) use FAD; use Getopt::Long qw(:config no_ignore_case); use Fatal qw( close unlink ); # obviate checking close()'s return code my(%mkfad_defined_errors) = ( mkfad_err_access => { fmt => '%s: can\'t %s' }, ); # Options my($opt_outfile, $opt_infile, $opt_nocrcs); sub mkfad { my($errstack_ref) = @_; my($rc, $in_handle, $out_handle); my(%data_store, $collected_info_ref); # Set ADE options ADE::register_error_types(\%mkfad_defined_errors); # Defaults for options $opt_outfile = undef; $opt_infile = undef; $opt_nocrcs = undef; # Register options if (($rc=ADE::register_options($errstack_ref, 'i:so:s', 'no-crcs,infile:s,outfile:s', 'main::mkfad_opt_handler_%s')) != $ADE::OK) { return($rc); } # Register handler functions if (($rc=ADE::set_callbacks($errstack_ref, \&mkfad_usage_help, \&mkfad_version, \&mkfad_paths)) != $ADE::OK) { return($rc); } # Process options ADE::debug($errstack_ref, 10, 'mkfad: processing options ...'); if (($rc=ADE::process_options($errstack_ref)) != $ADE::OK) { return($rc); } # Process arguments ADE::show_bad_usage($errstack_ref) if (defined $ARGV[0]); $rc = 0; # Open file list if specified if (defined $opt_infile) { if (($rc=ADE::open_compressed_file_for_reading($errstack_ref, $opt_infile, \*IN_HANDLE)) != $ADE::OK) { ADE::error($errstack_ref, 'mkfad_err_access', $opt_infile, 'open'); return($rc); } $in_handle = \*IN_HANDLE; } else { $in_handle = \*STDIN; } # Slurp file list, generate FAD records, and store in internal store while (<$in_handle>) { chomp; if (($rc=FAD::collect_info($errstack_ref, $_, $opt_nocrcs, \$collected_info_ref)) != $ADE::OK) { return($rc); # If there was a stat error, then FAD::collect_info() *succeeds* but sets $collected_info_ref # to undef. The reason for this is that there are so many transient files, that a fully successful # run is highly unlikely. However, we give a warning. } elsif (not defined $collected_info_ref) { ADE::warning($errstack_ref, 'ade_err_access', $_, 'access (did it disappear?)'); next; } return($rc) if (($rc=FAD::insert_info($errstack_ref, \%data_store, $collected_info_ref)) != $ADE::OK); } # Close input file if necessary if (defined $opt_infile) { close IN_HANDLE; } # Open output file if specified if (defined $opt_outfile) { ADE::debug($errstack_ref, 10, "mkfad: registering outfile $opt_outfile ..."); ADE::register_temp_file($errstack_ref, $opt_outfile); if (($rc=ADE::open_compressed_file_for_writing($errstack_ref, $opt_outfile, \*OUT_HANDLE)) != $ADE::OK) { ADE::error($errstack_ref, 'mkfad_err_access', $opt_outfile, 'open'); return($rc); } $out_handle = \*OUT_HANDLE; } else { ADE::debug($errstack_ref, 10, 'mkfad: outfile is stdout'); $out_handle = \*STDOUT; } # Print all records to the output handle. ADE::debug($errstack_ref, 10, 'mkfad: dumping records to outfile ...'); if (($rc=FAD::dump($errstack_ref, $out_handle, \%data_store)) != $ADE::OK) { return($rc); } # Close output file if necessary if (defined $opt_outfile) { close OUT_HANDLE; ADE::debug($errstack_ref, 10, "mkfad: deregistering $opt_outfile"); ADE::deregister_temp_file($errstack_ref, $opt_outfile); } # Now that we have finished with the FAD store, we can clear it of all records. undef %data_store; # Ensure sensible return code return($ADE::OK); } sub mkfad_opt_handler_i ## no critic (RequireArgUnpacking) { return(mkfad_opt_handler_infile(@_)); } sub mkfad_opt_handler_o ## no critic (RequireArgUnpacking) { return(mkfad_opt_handler_outfile(@_)); } sub mkfad_opt_handler_no_crcs { my($errstack_ref) = @_; $opt_nocrcs = 1; return($ADE::OK); } sub mkfad_opt_handler_infile { my($errstack_ref, $infile) = @_; $opt_infile = $infile; return($ADE::OK); } sub mkfad_opt_handler_outfile { my($errstack_ref, $outfile) = @_; $opt_outfile = $outfile; return($ADE::OK); } sub mkfad_version { my($errstack_ref, $version_text_ref) = @_; return(ADE::extract_version($errstack_ref, $app_svnid, $version_text_ref)); } sub mkfad_paths { my($errstack_ref, $pathlist_text_ref) = @_; my($rc); ${$pathlist_text_ref} = undef; return($ADE::OK); } sub mkfad_usage_help { my($errstack_ref, $usage_text_short_ref, $usage_text_long_ref) = @_; ${$usage_text_short_ref} = undef; ${$usage_text_long_ref} = " -i | --infile= read file list from \n" . " -o | --outfile= send output to \n" . " --no-crcs suppress content checksums\n"; return($ADE::OK); } ADE::main(\&mkfad);