Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/seek-bzip2/seek-bunzip.c
blob: cbfda73d836bbcf15efc2d23c6b5414ca05bd052 (plain)
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
#include <setjmp.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include "micro-bunzip.h"

#define BUF_SIZE 8192

/**
 * Seek the bunzip_data `bz` to a specific position in bits `pos` by lseeking
 * the underlying file descriptor and priming the buffer with appropriate
 * bits already consumed. This probably only makes sense for seeking to the
 * start of a compressed block.
 */
unsigned int seek_bits( bunzip_data *bd, unsigned long pos )
{
    off_t n_byte = pos / 8;
    char n_bit = pos % 8;

    // Seek the underlying file descriptor
    if ( lseek( bd->in_fd, n_byte, SEEK_SET ) != n_byte )
    {
        return -1;
    }

    // Init the buffer at the right bit position
    bd->inbufBitCount = bd->inbufPos = bd->inbufCount = 0;
    get_bits( bd, n_bit );

    // // Update the bit position counter to match
    // bd->inPosBits = pos;

    return pos;
}

/* Open, seek to block at pos, and uncompress */

int uncompressblock( int src_fd, unsigned long pos )
{
    bunzip_data *bd;
    int status;
    int gotcount;
    char outbuf[BUF_SIZE];

    if ( !( status = start_bunzip( &bd, src_fd, 0, 0 ) ) )
    {
        seek_bits( bd, pos );

        /* Fill the decode buffer for the block */
        if ( ( status = get_next_block( bd ) ) )
            goto seek_bunzip_finish;

        /* Init the CRC for writing */
        bd->writeCRC = 0xffffffffUL;

        /* Zero this so the current byte from before the seek is not written */
        bd->writeCopies = 0;

        /* Decompress the block and write to stdout */
        for ( ; ; )
        {
            gotcount = read_bunzip( bd, outbuf, BUF_SIZE );
            if ( gotcount < 0 )
            {
                status = gotcount;
                break;
            }
            else if ( gotcount == 0 )
            {
                break;
            }
            else
            {
                write( 1, outbuf, gotcount );
            }
        }
    }

seek_bunzip_finish:

    if ( bd->dbuf ) free( bd->dbuf );
    free( bd );

    return status;
}

int main( int argc, char *argv[] )
{
    unsigned long pos = atol( argv[1] );
    int status = uncompressblock( 0, pos );
    if ( status )
        fprintf( stderr, "\n%s\n", bunzip_errors[-status] );
}