forked from chokkan/seekgzip
-
Notifications
You must be signed in to change notification settings - Fork 2
/
main.c
135 lines (120 loc) · 3.41 KB
/
main.c
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
/*
* SeekGzip utility/library.
*
* Copyright (c) 2010-2011, Naoaki Okazaki
* All rights reserved.
*
* For conditions of distribution and use, see copyright notice in README
* or zlib.h.
*
* The core algorithm for random access originates from zran.c in zlib/gzip
* distribution. This code simply implements a data structure and algorithm
* for indices, wraps the functionality of random access as a library, and
* provides a command-line utility.
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include "seekgzip.h"
#define CHUNK 16384 /* file input buffer size */
static void seekgzip_perror(int ret)
{
switch (ret) {
case SEEKGZIP_ERROR:
fprintf(stderr, "ERROR: An unknown error occurred.\n");
break;
case SEEKGZIP_OPENERROR:
fprintf(stderr, "ERROR: Failed to open a file.\n");
break;
case SEEKGZIP_READERROR:
fprintf(stderr, "ERROR: Failed to read a file.\n");
break;
case SEEKGZIP_WRITEERROR:
fprintf(stderr, "ERROR: Failed to write a file.\n");
break;
case SEEKGZIP_DATAERROR:
fprintf(stderr, "ERROR: The file is corrupted.\n");
break;
case SEEKGZIP_OUTOFMEMORY:
fprintf(stderr, "ERROR: Out of memory.\n");
break;
case SEEKGZIP_IMCOMPATIBLE:
fprintf(stderr, "ERROR: The imcompatible file.\n");
break;
case SEEKGZIP_ZLIBERROR:
fprintf(stderr, "ERROR: An error occurred in zlib.\n");
break;
}
}
int main(int argc, char *argv[])
{
int ret = 0;
if (argc != 3) {
printf("This utility manages an index for random (seekable) access to a gzip file.\n");
printf("USAGE:\n");
printf(" %s -b <FILE>\n", argv[0]);
printf(" Build an index file \"$FILE.idx\" for the gzip file $FILE.\n");
printf(" %s <FILE> [BEGIN-END]\n", argv[0]);
printf(" Output the content of the gzip file $FILE of offset range [BEGIN-END].\n");
return 0;
} else if (strcmp(argv[1], "-b") == 0) {
const char *target = argv[2];
printf("Building an index: %s.idx\n", target);
printf("Filesize up to: %d bit\n", (int)sizeof(off_t) * 8);
printf("WARNING: if program fail to write index to file, it would silently ignore that\n");
seekgzip_t* zs = seekgzip_open(target, 0);
if ((ret = seekgzip_error(zs)) != SEEKGZIP_SUCCESS) {
seekgzip_perror(ret);
return 1;
}
seekgzip_close(zs);
return 0;
} else {
char *arg = argv[2], *p = NULL;
off_t begin = 0, end = (off_t)-1;
seekgzip_t* zs = seekgzip_open(argv[1], 0);
if (zs == NULL || seekgzip_error(zs) != SEEKGZIP_SUCCESS) {
fprintf(stderr, "ERROR: Failed to open the index file.\n");
return 1;
}
p = strchr(arg, '-');
if (p == NULL) {
begin =(off_t)strtoull(arg, NULL, 10);
end = begin+1;
} else if (p == arg) {
begin = 0;
end = (off_t)strtoull(p+1, NULL, 10);
} else if (p == arg + strlen(arg) - 1) {
*p = 0;
begin = (off_t)strtoull(arg, NULL, 10);
} else {
*p++ = 0;
begin =(off_t)strtoull(arg, NULL, 10);
end =(off_t)strtoull(p, NULL, 10);
}
seekgzip_seek(zs, begin);
while (begin < end) {
int read;
char buffer[CHUNK];
off_t size = (end - begin);
if (CHUNK < size) {
size = CHUNK;
}
read = seekgzip_read(zs, buffer, (int)size);
if (0 < read) {
begin += read;
if(fwrite(buffer, read, sizeof(char), stdout) == 0)
continue;
} else if (read == 0) {
break;
} else {
fprintf(stderr, "ERROR: An error occurred while reading the gzip file.\n");
ret = 1;
break;
}
}
seekgzip_close(zs);
return ret;
}
}