File: debinhex.pl

package info (click to toggle)
libconvert-binhex-perl 1.119%2Bpristine-3
  • links: PTS, VCS
  • area: main
  • in suites: lenny, squeeze, wheezy
  • size: 312 kB
  • ctags: 137
  • sloc: perl: 838; makefile: 45
file content (211 lines) | stat: -rwxr-xr-x 5,503 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
#!/usr/bin/perl -w


=head1 NAME

debinhex.pl - use Convert::BinHex to decode BinHex files


=head1 USAGE

Usage:

    debinhex.pl [options] file ... file
     
Where the options are:

    -o dir    Output in given directory (default outputs in file's directory)
    -v        Verbose output (normally just one line per file is shown)

=head1 DESCRIPTION

Each file is expected to be a BinHex file.  By default, the output file is
given the name that the BinHex file dictates, regardless of the name of
the BinHex file.


=head1 WARNINGS

Largely untested.


=head1 AUTHOR

Paul J. Schinder (NASA/GSFC) mostly, though Eryq can't seem to keep
his grubby paws off anything...


=cut

use lib "./lib";

use Getopt::Std;				 
use Convert::BinHex;
use POSIX;
use Fcntl;
use File::Basename;
use Carp;
require Mac::Files if ($^O||'' eq "MacOS");

use strict;
use vars qw(
            $opt_o
            $opt_v
);

my $DEBUG = 0;

#------------------------------------------------------------
# main
#------------------------------------------------------------
sub main {

    # What usage?
    @ARGV or usage();
    getopts('o:v');
    $DEBUG = $opt_v;

    # Process files:
    my $file;
    foreach $file (@ARGV) {
	debinhex($file);
    }
}
exit(&main ? 0 : -1);

#------------------------------------------------------------
# usage
#------------------------------------------------------------
# Get usage from me.

sub usage {
    my $msg = shift || '';
    my $usage = '';
    if (open(USAGE, "<$0")) {
        while ($_ = <USAGE> and !/^=head1 USAGE/) {};
        while ($_ = <USAGE> and !/^=head1/) {$usage .= $_};
        close USAGE;
    }
    else {
        $usage = "Usage unavailable; please see the script itself.";
    }
    print STDERR "\n$msg$usage";
    exit -1;
}

#------------------------------------------------------------
# debinhex FILE
#------------------------------------------------------------
# Decode the given FILE.
#
sub debinhex {
    my $inpath = shift || croak("No filename given $!");
    local *BHEX;
    my ($data, $testlength, $length, $fd);

    print "DeBinHexing: $inpath\n";

    # Open BinHex file:
    open(BHEX,"<$inpath") || croak("Unable to open $inpath: $!");

    # Create converter interface on stream:
    my $hqx = Convert::BinHex->open(FH => \*BHEX);

    # Read header, and output as string if debugging:
    $hqx->read_header;
    print $hqx->header_as_string if $DEBUG;

    # Get output directory/filename:
    my ($inname, $indir) = fileparse($inpath);
    my $outname = $hqx->filename || 'NONAME';
    my $outdir  = $opt_o || $indir;
    my $outpath = "$outdir/$outname"; $outpath =~ s{/+}{/}g;

    # Create Mac file:
    if ($^O||'' eq "MacOS") {
        Mac::Files::FSpCreate($outpath, $hqx->creator, $hqx->type)
           or croak("Unable to create Mac file $outpath");
    }

    # Get lengths of forks:
    my $dlength = $hqx->data_length;
    my $rlength = $hqx->resource_length;

    # Write data fork:
    print "Writing:     $outpath\n";
    $fd = POSIX::open($outpath, (&POSIX::O_WRONLY | &POSIX::O_CREAT), 0755);
    $testlength = 0;
    while (defined($data = $hqx->read_data)) {
        $length = length($data);
        POSIX::write($fd, $data, $length)
	    or croak("couldn't write $length bytes: $!");
        $testlength += $length;
    }
    POSIX::close($fd) or croak "Unable to close $outpath";
    croak("Data fork length mismatch: ".
	  "expected $dlength, wrote $testlength")
        if $dlength != $testlength;

    # Write resource fork?
    if ($rlength) {

	# Determine how to open fork file appropriately:
	my ($rpath, $rflags);
        if (($^O||'') eq "MacOS") {
	    $rpath  = $outpath;
	    $rflags = (&POSIX::O_WRONLY | &POSIX::O_CREAT | &Fcntl::O_RSRC);
        } 
	else {
	    $rpath  = "$outpath.rsrc";
	    $rflags = (&POSIX::O_WRONLY | &POSIX::O_CREAT);
        }	

	# Write resource fork...
	$fd = POSIX::open($rpath, $rflags, 0755);
        $testlength = 0;
        while (defined($data = $hqx->read_resource)) {
            $length = length($data);
	    POSIX::write($fd,$data,$length)
		or croak "Couldn't write $length bytes: $!";
            $testlength += $length;
        }
        POSIX::close($fd) or croak "Unable to close $rpath";
        croak("Resource fork length mismatch: ".
	      "expected $rlength, wrote $testlength")
	    if $testlength != $rlength;
    }

    # Set Mac attributes:
    if (($^O||'') eq "MacOS") {
        my $has = Mac::Files::FSpGetCatInfo($outpath);
        my $finfo = $has->{ioFlFndrInfo};
        $finfo->{fdFlags}   = $hqx->flags & 0xfeff; #turn off inited bit
        $finfo->{fdType}    = $hqx->type || "????";
        $finfo->{fdCreator} = $hqx->creator || "????";

        # Turn on the bundle bit if it's an application:
###     $finfo->{fdFlags} |= 0x2000 if $finfo->{fdType} eq "APPL";

        if ($DEBUG) {
            printf("%x\n",$finfo->{fdFlags});
            printf("%s\n",$finfo->{fdType});
            printf("%s\n",$finfo->{fdCreator});
        }
        $has->{ioFlFndrInfo} = $finfo;
        Mac::Files::FSpSetCatInfo($outpath, $has)
        	or croak "Unable to set catalog info $^E";
        if ($DEBUG) {
            $has = Mac::Files::FSpGetCatInfo ($outpath);
            printf("%x\n",$has->{ioFlFndrInfo}->{fdFlags});
            printf("%s\n",$has->{ioFlFndrInfo}->{fdType});
            printf("%s\n",$has->{ioFlFndrInfo}->{fdCreator});
        }
    }
    1;
}

#------------------------------------------------------------
1;