-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathlinix
executable file
·77 lines (71 loc) · 2.57 KB
/
linix
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
#!/usr/bin/perl
use strict;
use warnings;
use Fcntl qw(:seek);
my $USAGE=q/ Usage:
linix <text_file> [line_number]
If a single argument is provided, an index file will be created
If two arguments are provided, the specified line will be read from the text file
/;
my $ftxt = $ARGV[0];
if (!defined $ARGV[0] || $ARGV[0] eq '-h' || $ARGV[0] eq '--help' || !-f $ARGV[0]) {
die $USAGE;
}
my $fidx = "$ftxt.lidx";
my $linereq=defined $ARGV[1]; # line request mode
my $text_mtime = (stat($ftxt))[9];
my $index_mtime = -f $fidx ? (stat($fidx))[9] : 0;
my $lcount=0;
if ($text_mtime > $index_mtime) {
print STDERR ".. creating index file: $fidx\n" if $linereq;
create_index()
} #elsif (!$linereq) {
#print STDERR " existing index seems up to date.";
#}
my $index_size = -s $fidx;
my $total_lines = $index_size / 8;
if ($linereq) { # line retrieval requested
my $lno = $ARGV[1];
die("${USAGE}Error: invalid line number requested ($lno)\n") if $lno<1 || $lno > 65534;
die("Error: invalid line requested (max is $total_lines)\n") if $lno>$total_lines;
read_line($lno);
} else { # just indexing request, print out the number of indexed lines
print "$total_lines indexed lines.\n";
}
##---------------- subroutines
sub create_index {
#detect_line_ending
open my $fh, '<', $ftxt or die "Could not open '$ftxt': $!";
my $first_line = <$fh>;
close $fh;
my $eol=($first_line =~ /\r\n/ ? "\r\n" : "\n");
open my $txt_fh, '<', $ftxt or die "Could not open '$ftxt': $!";
open my $idx_fh, '>', $fidx or die "Could not create '$fidx': $!";
my $offset = 0;
my $lno = 0;
while (<$txt_fh>) {
$lno++;
my $clen = length($_)-length($eol);
print $idx_fh pack('S I S', $lno, $offset, $clen);
$offset += length($_);
}
close $txt_fh;
close $idx_fh;
}
sub read_line {
my ($reqlno) = @_;
open my $idx_fh, '<', $fidx or die "Could not open '$fidx': $!";
my $index_offset = ($reqlno - 1) * 8;
seek $idx_fh, $index_offset, SEEK_SET;
read $idx_fh, my $record, 8;
close $idx_fh;
my ($lno, $offset, $clen) = unpack('S I S', $record);
die "Error: line number mismatch in index file!\n" if !defined($lno) || $lno != $reqlno;
open my $txt_fh, '<', $ftxt or die "Could not open '$ftxt': $!";
seek($txt_fh, $offset, SEEK_SET) || die "Error seeking to $offset in $ftxt : $!\n";
my $line='------------------------------------------------------------------';
my $brd=read($txt_fh, $line, $clen);
die "Error reading line $reqlno from $ftxt : $!\n" if !defined($brd);
close $txt_fh;
print $line."\n";
}