1 /* htsfile.c -- file identifier and minimal viewer.
3 Copyright (C) 2014-2017 Genome Research Ltd.
5 Author: John Marshall <jm18@sanger.ac.uk>
7 Permission is hereby granted, free of charge, to any person obtaining a copy
8 of this software and associated documentation files (the "Software"), to deal
9 in the Software without restriction, including without limitation the rights
10 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 copies of the Software, and to permit persons to whom the Software is
12 furnished to do so, subject to the following conditions:
14 The above copyright notice and this permission notice shall be included in
15 all copies or substantial portions of the Software.
17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23 DEALINGS IN THE SOFTWARE. */
36 #include "htslib/hfile.h"
37 #include "htslib/hts.h"
38 #include "htslib/sam.h"
39 #include "htslib/vcf.h"
41 enum { identify
, view_headers
, view_all
} mode
= identify
;
44 int status
= EXIT_SUCCESS
; /* Exit status from main */
46 void error(const char *format
, ...)
50 va_start(args
, format
);
52 fprintf(stderr
, "htsfile: ");
53 vfprintf(stderr
, format
, args
);
54 if (err
) fprintf(stderr
, ": %s\n", strerror(err
));
55 else fprintf(stderr
, "\n");
58 status
= EXIT_FAILURE
;
61 static htsFile
*dup_stdout(const char *mode
)
63 int fd
= dup(STDOUT_FILENO
);
64 hFILE
*hfp
= (fd
>= 0)? hdopen(fd
, mode
) : NULL
;
65 return hfp
? hts_hopen(hfp
, "-", mode
) : NULL
;
68 static void view_sam(samFile
*in
, const char *filename
)
71 bam_hdr_t
*hdr
= NULL
;
74 hdr
= sam_hdr_read(in
);
76 errno
= 0; error("reading headers from \"%s\" failed", filename
);
80 out
= dup_stdout("w");
81 if (out
== NULL
) { error("reopening standard output failed"); goto clean
; }
84 if (sam_hdr_write(out
, hdr
) != 0) {
85 error("writing headers to standard output failed");
90 if (mode
== view_all
) {
94 if (b
== NULL
) { error("can't create record"); goto clean
; }
96 while ((ret
= sam_read1(in
, hdr
, b
)) >= 0) {
97 if (sam_write1(out
, hdr
, b
) < 0) {
98 error("writing to standard output failed");
103 if (ret
< -1) { error("reading \"%s\" failed", filename
); goto clean
; }
107 bam_hdr_destroy(hdr
);
109 if (out
) hts_close(out
);
112 static void view_vcf(vcfFile
*in
, const char *filename
)
115 bcf_hdr_t
*hdr
= NULL
;
118 hdr
= bcf_hdr_read(in
);
120 errno
= 0; error("reading headers from \"%s\" failed", filename
);
124 out
= dup_stdout("w");
125 if (out
== NULL
) { error("reopening standard output failed"); goto clean
; }
128 if (bcf_hdr_write(out
, hdr
) != 0) {
129 error("writing headers to standard output failed");
134 if (mode
== view_all
) {
138 if (rec
== NULL
) { error("can't create record"); goto clean
; }
140 while ((ret
= bcf_read(in
, hdr
, rec
)) >= 0) {
141 if (bcf_write(out
, hdr
, rec
) < 0) {
142 error("writing to standard output failed");
147 if (ret
< -1) { error("reading \"%s\" failed", filename
); goto clean
; }
151 if (hdr
) bcf_hdr_destroy(hdr
);
152 if (rec
) bcf_destroy(rec
);
153 if (out
) hts_close(out
);
156 static void view_raw(hFILE
*fp
, const char *filename
)
159 for (prev
= '\n'; (c
= hgetc(fp
)) != EOF
; prev
= c
)
160 if (isprint(c
) || c
== '\n' || c
== '\t') putchar(c
);
161 else if (c
== '\r') fputs("\\r", stdout
);
162 else if (c
== '\0') fputs("\\0", stdout
);
163 else printf("\\x%02x", c
);
165 if (prev
!= '\n') putchar('\n');
169 error("reading \"%s\" failed", filename
);
173 static void usage(FILE *fp
, int status
)
176 "Usage: htsfile [-chHv] FILE...\n"
178 " -c, --view Write textual form of FILEs to standard output\n"
179 " -h, --header-only Display only headers in view mode, not records\n"
180 " -H, --no-header Suppress header display in view mode\n"
181 " -v, --verbose Increase verbosity of warnings and diagnostics\n");
185 int main(int argc
, char **argv
)
187 static const struct option options
[] = {
188 { "header-only", no_argument
, NULL
, 'h' },
189 { "no-header", no_argument
, NULL
, 'H' },
190 { "view", no_argument
, NULL
, 'c' },
191 { "verbose", no_argument
, NULL
, 'v' },
192 { "help", no_argument
, NULL
, '?' },
193 { "version", no_argument
, NULL
, 1 },
199 status
= EXIT_SUCCESS
;
200 while ((c
= getopt_long(argc
, argv
, "chHv?", options
, NULL
)) >= 0)
202 case 'c': mode
= view_all
; break;
203 case 'h': mode
= view_headers
; show_headers
= 1; break;
204 case 'H': show_headers
= 0; break;
205 case 'v': hts_verbose
++; verbose
++; break;
208 "htsfile (htslib) %s\n"
209 "Copyright (C) 2017 Genome Research Ltd.\n",
213 case '?': usage(stdout
, EXIT_SUCCESS
); break;
214 default: usage(stderr
, EXIT_FAILURE
); break;
217 if (optind
== argc
) usage(stderr
, EXIT_FAILURE
);
219 for (i
= optind
; i
< argc
; i
++) {
220 hFILE
*fp
= hopen(argv
[i
], "r");
222 error("can't open \"%s\"", argv
[i
]);
226 if (mode
== identify
) {
228 if (hts_detect_format(fp
, &fmt
) < 0) {
229 error("detecting \"%s\" format failed", argv
[i
]);
234 char *description
= hts_format_description(&fmt
);
235 printf("%s:\t%s\n", argv
[i
], description
);
239 htsFile
*hts
= hts_hopen(fp
, argv
[i
], "r");
241 switch (hts_get_format(hts
)->category
) {
243 view_sam(hts
, argv
[i
]);
246 view_vcf(hts
, argv
[i
]);
250 view_raw(fp
, argv
[i
]);
253 error("can't view \"%s\": unknown format", argv
[i
]);
258 if (hts_close(hts
) < 0) error("closing \"%s\" failed", argv
[i
]);
261 else if (errno
== ENOEXEC
&& verbose
)
262 view_raw(fp
, argv
[i
]);
264 error("can't view \"%s\"", argv
[i
]);
267 if (fp
&& hclose(fp
) < 0) error("closing \"%s\" failed", argv
[i
]);