From ca535cf5321de0a93406b8534f6bc03d01fb5644 Mon Sep 17 00:00:00 2001 From: On behalf of John Marshall Date: Wed, 22 Sep 2010 15:15:33 +0000 Subject: [PATCH] When bam_read1() returns an error (return value <= -2), propagate that error to bam_iter_read()'s own return value. Similarly, also propagate it up to bam_fetch()'s return value. Previously bam_fetch() always returned 0, and callers ignored its return value anyway. With this change, 0 continues to indicate success, while <= -2 (which can be written as < 0, as -1 is never returned) indicates corrupted input. bam_iter_read() ought also to propagate errors returned by bam_seek(). main_samview() can now print an error message and fail when bam_fetch() detects that a .bai index file is corrupted or otherwise does not correspond to the .bam file it is being used with. --- bam_index.c | 17 +++++++++-------- sam_view.c | 7 ++++++- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/bam_index.c b/bam_index.c index 9d819d3..263561b 100644 --- a/bam_index.c +++ b/bam_index.c @@ -656,17 +656,17 @@ void bam_iter_destroy(bam_iter_t iter) int bam_iter_read(bamFile fp, bam_iter_t iter, bam1_t *b) { + int ret; if (iter && iter->finished) return -1; if (iter == 0 || iter->from_first) { - int ret = bam_read1(fp, b); + ret = bam_read1(fp, b); if (ret < 0 && iter) iter->finished = 1; return ret; } if (iter->off == 0) return -1; for (;;) { - int ret; if (iter->curr_off == 0 || iter->curr_off >= iter->off[iter->i].v) { // then jump to the next chunk - if (iter->i == iter->n_off - 1) break; // no more chunks + if (iter->i == iter->n_off - 1) { ret = -1; break; } // no more chunks if (iter->i >= 0) assert(iter->curr_off == iter->off[iter->i].v); // otherwise bug if (iter->i < 0 || iter->off[iter->i].v != iter->off[iter->i+1].u) { // not adjacent chunks; then seek bam_seek(fp, iter->off[iter->i+1].u, SEEK_SET); @@ -676,21 +676,22 @@ int bam_iter_read(bamFile fp, bam_iter_t iter, bam1_t *b) } if ((ret = bam_read1(fp, b)) >= 0) { iter->curr_off = bam_tell(fp); - if (b->core.tid != iter->tid || b->core.pos >= iter->end) break; // no need to proceed + if (b->core.tid != iter->tid || b->core.pos >= iter->end) { ret = -1; break; } // no need to proceed else if (is_overlap(iter->beg, iter->end, b)) return ret; - } else break; // end of file + } else break; // end of file or error } iter->finished = 1; - return -1; + return ret; } int bam_fetch(bamFile fp, const bam_index_t *idx, int tid, int beg, int end, void *data, bam_fetch_f func) { + int ret; bam_iter_t iter; bam1_t *b; b = bam_init1(); iter = bam_iter_query(idx, tid, beg, end); - while (bam_iter_read(fp, iter, b) >= 0) func(b, data); + while ((ret = bam_iter_read(fp, iter, b)) >= 0) func(b, data); bam_destroy1(b); - return 0; + return (ret == -1)? 0 : ret; } diff --git a/sam_view.c b/sam_view.c index 3b10e2e..41b651a 100644 --- a/sam_view.c +++ b/sam_view.c @@ -164,7 +164,12 @@ int main_samview(int argc, char *argv[]) fprintf(stderr, "[main_samview] fail to get the reference name. Continue anyway.\n"); continue; } - bam_fetch(in->x.bam, idx, tid, beg, end, out, view_func); // fetch alignments + // fetch alignments + if (bam_fetch(in->x.bam, idx, tid, beg, end, out, view_func) < 0) { + fprintf(stderr, "[main_samview] retrieval failed due to truncated file or corrupt BAM index file\n"); + ret = 1; + break; + } } bam_index_destroy(idx); // destroy the BAM index } -- 2.39.5