The 1.8 tarball does not contain Windows binaries anymore.
[samtools.git] / razip.c
1 #include <stdio.h>
2 #include <fcntl.h>
3 #include <unistd.h>
4 #include <errno.h>
5 #include <stdlib.h>
6 #include <string.h>
7 #include "razf.h"
8
9 #define WINDOW_SIZE 4096
10
11 static int razf_main_usage()
12 {
13         printf("\n");
14         printf("Usage:   razip [options] [file] ...\n\n");
15         printf("Options: -c      write on standard output, keep original files unchanged\n");
16         printf("         -d      decompress\n");
17         printf("         -l      list compressed file contents\n");
18         printf("         -b INT  decompress at INT position in the uncompressed file\n");
19         printf("         -s INT  decompress INT bytes in the uncompressed file\n");
20         printf("         -h      give this help\n");
21         printf("\n");
22         return 0;
23 }
24
25 static int write_open(const char *fn, int is_forced)
26 {
27         int fd = -1;
28         char c;
29         if (!is_forced) {
30                 if ((fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, 0666)) < 0 && errno == EEXIST) {
31                         printf("razip: %s already exists; do you wish to overwrite (y or n)? ", fn);
32                         scanf("%c", &c);
33                         if (c != 'Y' && c != 'y') {
34                                 printf("razip: not overwritten\n");
35                                 exit(1);
36                         }
37                 }
38         }
39         if (fd < 0) {
40                 if ((fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC, 0666)) < 0) {
41                         fprintf(stderr, "razip: %s: Fail to write\n", fn);
42                         exit(1);
43                 }
44         }
45         return fd;
46 }
47
48 int main(int argc, char **argv)
49 {
50         int c, compress, pstdout, is_forced;
51         RAZF *rz;
52         void *buffer;
53         long start, end, size;
54
55         compress = 1; pstdout = 0; start = 0; size = -1; end = -1; is_forced = 0;
56         while((c  = getopt(argc, argv, "cdlhfb:s:")) >= 0){
57                 switch(c){
58                 case 'h': return razf_main_usage();
59                 case 'd': compress = 0; break;
60                 case 'c': pstdout = 1; break;
61                 case 'l': compress = 2; break;
62                 case 'b': start = atol(optarg); break;
63                 case 's': size = atol(optarg); break;
64                 case 'f': is_forced = 1; break;
65                 }
66         }
67         if (size >= 0) end = start + size;
68         if(end >= 0 && end < start){
69                 fprintf(stderr, " -- Illegal region: [%ld, %ld] --\n", start, end);
70                 return 1;
71         }
72         if(compress == 1){
73                 int f_src, f_dst = -1;
74                 if(argc > optind){
75                         if((f_src = open(argv[optind], O_RDONLY)) < 0){
76                                 fprintf(stderr, " -- Cannot open file: %s --\n", argv[optind]);
77                                 return 1;
78                         }
79                         if(pstdout){
80                                 f_dst = fileno(stdout);
81                         } else {
82                                 char *name = malloc(sizeof(strlen(argv[optind]) + 5));
83                                 strcpy(name, argv[optind]);
84                                 strcat(name, ".rz");
85                                 f_dst = write_open(name, is_forced);
86                                 if (f_dst < 0) return 1;
87                                 free(name);
88                         }
89                 } else if(pstdout){ 
90                         f_src = fileno(stdin);
91                         f_dst = fileno(stdout);
92                 } else return razf_main_usage();
93                 rz = razf_dopen(f_dst, "w");
94                 buffer = malloc(WINDOW_SIZE);
95                 while((c = read(f_src, buffer, WINDOW_SIZE)) > 0) razf_write(rz, buffer, c);
96                 razf_close(rz); // f_dst will be closed here
97                 if (argc > optind) unlink(argv[optind]);
98                 free(buffer);
99                 close(f_src);
100                 return 0;
101         } else {
102                 if(argc <= optind) return razf_main_usage();
103                 if(compress == 2){
104                         rz = razf_open(argv[optind], "r");
105                         if(rz->file_type == FILE_TYPE_RZ) {
106                                                         printf("%20s%20s%7s %s\n", "compressed", "uncompressed", "ratio", "name");
107                                 printf("%20lld%20lld%6.1f%% %s\n", (long long)rz->end, (long long)rz->src_end, rz->end * 100.0f / rz->src_end,
108                                            argv[optind]);
109                         } else fprintf(stdout, "%s is not a regular rz file\n", argv[optind]);
110                 } else {
111                         int f_dst;
112                         if (argc > optind && !pstdout) {
113                                 char *name;
114                                 if (strstr(argv[optind], ".rz") - argv[optind] != strlen(argv[optind]) - 3) {
115                                         printf("razip: %s: unknown suffix -- ignored\n", argv[optind]);
116                                         return 1;
117                                 }
118                                 name = strdup(argv[optind]);
119                                 name[strlen(name) - 3] = '\0';
120                                 f_dst = write_open(name, is_forced);
121                                 free(name);
122                         } else f_dst = fileno(stdout);
123                         rz = razf_open(argv[optind], "r");
124                         buffer = malloc(WINDOW_SIZE);
125                         razf_seek(rz, start, SEEK_SET);
126                         while(1){
127                                 if(end < 0) c = razf_read(rz, buffer, WINDOW_SIZE);
128                                 else c = razf_read(rz, buffer, (end - start > WINDOW_SIZE)? WINDOW_SIZE:(end - start));
129                                 if(c <= 0) break;
130                                 start += c;
131                                 write(f_dst, buffer, c);
132                                 if(end >= 0 && start >= end) break;
133                         }
134                         free(buffer);
135                         if (!pstdout) unlink(argv[optind]);
136                 }
137                 razf_close(rz);
138                 return 0;
139         }
140 }
141