From 8cab5e6afd245a6dbbb1580dc37cd3ee36e55078 Mon Sep 17 00:00:00 2001 From: Heng Li Date: Thu, 2 Jul 2009 10:32:26 +0000 Subject: [PATCH] * samtools-0.1.4-21 (r368) * propagate errors rather than exit or complain assertion failure. Assertion should be only used for checking internal bugs, but not for external input inconsistency. I was just a bit lazy. * small memory leak may be present on failure, though --- bam.c | 1 + bam.h | 4 ++-- bam_aux.c | 12 ++++++++---- bam_index.c | 18 ++++++++++++------ bam_lpileup.c | 1 + bam_md.c | 1 + bam_pileup.c | 12 +++++++++--- bam_rmdup.c | 1 - bam_stat.c | 1 + bam_tview.c | 1 + bamtk.c | 3 ++- faidx.c | 46 ++++++++++++++++++++++++++++++++-------------- faidx.h | 3 ++- glf.c | 5 +++-- 14 files changed, 75 insertions(+), 34 deletions(-) diff --git a/bam.c b/bam.c index 7f1ecfd..1ff4a5a 100644 --- a/bam.c +++ b/bam.c @@ -1,5 +1,6 @@ #include #include +#include #include "bam.h" #include "bam_endian.h" #include "kstring.h" diff --git a/bam.h b/bam.h index 6316c9b..a2ceb17 100644 --- a/bam.h +++ b/bam.h @@ -41,7 +41,6 @@ */ #include -#include #include #include #include @@ -600,8 +599,9 @@ extern "C" { @param ref_id the returned chromosome ID @param begin the returned start coordinate @param end the returned end coordinate + @return 0 on success; -1 on failure */ - void bam_parse_region(bam_header_t *header, const char *str, int *ref_id, int *begin, int *end); + int bam_parse_region(bam_header_t *header, const char *str, int *ref_id, int *begin, int *end); /*! @abstract Retrieve data of a tag diff --git a/bam_aux.c b/bam_aux.c index a63e2ae..9b91842 100644 --- a/bam_aux.c +++ b/bam_aux.c @@ -72,7 +72,7 @@ int32_t bam_get_tid(const bam_header_t *header, const char *seq_name) return k == kh_end(h)? -1 : kh_value(h, k); } -void bam_parse_region(bam_header_t *header, const char *str, int *ref_id, int *begin, int *end) +int bam_parse_region(bam_header_t *header, const char *str, int *ref_id, int *begin, int *end) { char *s, *p; int i, l, k; @@ -93,12 +93,12 @@ void bam_parse_region(bam_header_t *header, const char *str, int *ref_id, int *b iter = kh_get(s, h, s); /* get the ref_id */ if (iter == kh_end(h)) { // name not found *ref_id = -1; free(s); - return; + return -1; } *ref_id = kh_value(h, iter); if (i == k) { /* dump the whole sequence */ *begin = 0; *end = 1<<29; free(s); - return; + return -1; } for (p = s + i + 1; i != k; ++i) if (s[i] == '-') break; *begin = atoi(p); @@ -107,8 +107,12 @@ void bam_parse_region(bam_header_t *header, const char *str, int *ref_id, int *b *end = atoi(p); } else *end = 1<<29; if (*begin > 0) --*begin; - assert(*begin <= *end); free(s); + if (*begin > *end) { + fprintf(stderr, "[bam_parse_region] invalid region.\n"); + return -1; + } + return 0; } int32_t bam_aux2i(const uint8_t *s) diff --git a/bam_index.c b/bam_index.c index 329df32..72ef270 100644 --- a/bam_index.c +++ b/bam_index.c @@ -1,4 +1,5 @@ #include +#include #include "bam.h" #include "khash.h" #include "ksort.h" @@ -324,7 +325,6 @@ static bam_index_t *bam_index_load_core(FILE *fp) bam_index_t *bam_index_load_local(const char *_fn) { - bam_index_t *idx; FILE *fp; char *fnidx, *fn; @@ -347,9 +347,11 @@ bam_index_t *bam_index_load_local(const char *_fn) } } free(fnidx); free(fn); - idx = bam_index_load_core(fp); - fclose(fp); - return idx; + if (fp) { + bam_index_t *idx = bam_index_load_core(fp); + fclose(fp); + return idx; + } else return 0; } static void download_from_remote(const char *url) @@ -394,6 +396,7 @@ bam_index_t *bam_index_load(const char *fn) download_from_remote(fnidx); idx = bam_index_load_local(fn); } + if (idx == 0) fprintf(stderr, "[bam_index_load] fail to load BAM index.\n"); return idx; } @@ -403,7 +406,10 @@ int bam_index_build2(const char *fn, const char *_fnidx) FILE *fpidx; bamFile fp; bam_index_t *idx; - assert(fp = bam_open(fn, "r")); + if ((fp = bam_open(fn, "r")) == 0) { + fprintf(stderr, "[bam_index_build2] fail to open the BAM file.\n"); + return -1; + } idx = bam_index_core(fp); bam_close(fp); if (_fnidx == 0) { @@ -414,7 +420,7 @@ int bam_index_build2(const char *fn, const char *_fnidx) if (fpidx == 0) { fprintf(stderr, "[bam_index_build2] fail to create the index file.\n"); free(fnidx); - return 1; + return -1; } bam_index_save(idx, fpidx); bam_index_destroy(idx); diff --git a/bam_lpileup.c b/bam_lpileup.c index 1562170..425290e 100644 --- a/bam_lpileup.c +++ b/bam_lpileup.c @@ -1,5 +1,6 @@ #include #include +#include #include "bam.h" #include "ksort.h" diff --git a/bam_md.c b/bam_md.c index 9abff46..a20f9b3 100644 --- a/bam_md.c +++ b/bam_md.c @@ -1,4 +1,5 @@ #include +#include #include #include #include "faidx.h" diff --git a/bam_pileup.c b/bam_pileup.c index 46906db..3ffd528 100644 --- a/bam_pileup.c +++ b/bam_pileup.c @@ -1,6 +1,7 @@ #include #include #include +#include #include "sam.h" typedef struct __linkbuf_t { @@ -61,7 +62,7 @@ static inline int resolve_cigar(bam_pileup1_t *p, uint32_t pos) int ret = 1, is_restart = 1; if (c->flag&BAM_FUNMAP) return 0; // unmapped read - assert(x <= pos); + assert(x <= pos); // otherwise a bug p->qpos = -1; p->indel = 0; p->is_del = p->is_head = p->is_tail = 0; for (k = 0; k < c->n_cigar; ++k) { int op = bam1_cigar(b)[k] & BAM_CIGAR_MASK; // operation @@ -97,7 +98,7 @@ static inline int resolve_cigar(bam_pileup1_t *p, uint32_t pos) break; } } - assert(x > pos); + assert(x > pos); // otherwise a bug return ret; } @@ -196,7 +197,12 @@ int bam_plbuf_push(const bam1_t *b, bam_plbuf_t *buf) buf->func(buf->tid, buf->pos, n_pu, buf->pu, buf->func_data); } // update tid and pos - if (buf->head->next) assert(buf->tid <= buf->head->b.core.tid); // otherwise, not sorted + if (buf->head->next) { + if (buf->tid > buf->head->b.core.tid) { + fprintf(stderr, "[bam_plbuf_push] unsorted input. Pileup aborts.\n"); + return 1; + } + } if (buf->tid < buf->head->b.core.tid) { // come to a new reference sequence buf->tid = buf->head->b.core.tid; buf->pos = buf->head->beg; // jump to the next reference } else if (buf->pos < buf->head->beg) { // here: tid == head->b.core.tid diff --git a/bam_rmdup.c b/bam_rmdup.c index 5026901..1fa6cad 100644 --- a/bam_rmdup.c +++ b/bam_rmdup.c @@ -1,7 +1,6 @@ #include #include #include -#include #include #include "bam.h" diff --git a/bam_stat.c b/bam_stat.c index 81b7b63..c1c4a43 100644 --- a/bam_stat.c +++ b/bam_stat.c @@ -1,4 +1,5 @@ #include +#include #include "bam.h" typedef struct { diff --git a/bam_tview.c b/bam_tview.c index e5b83a1..be2579c 100644 --- a/bam_tview.c +++ b/bam_tview.c @@ -161,6 +161,7 @@ tview_t *tv_init(const char *fn, const char *fn_fa) tview_t *tv = (tview_t*)calloc(1, sizeof(tview_t)); tv->is_dot = 1; tv->idx = bam_index_load(fn); + if (tv->idx == 0) exit(1); tv->fp = bam_open(fn, "r"); bgzf_set_cache_size(tv->fp, 8 * 1024 *1024); assert(tv->fp); diff --git a/bamtk.c b/bamtk.c index 61ead10..9876279 100644 --- a/bamtk.c +++ b/bamtk.c @@ -1,9 +1,10 @@ #include #include +#include #include "bam.h" #ifndef PACKAGE_VERSION -#define PACKAGE_VERSION "0.1.4-20 (r365)" +#define PACKAGE_VERSION "0.1.4-21 (r368)" #endif int bam_taf2baf(int argc, char *argv[]); diff --git a/faidx.c b/faidx.c index 6b4514f..36366c2 100644 --- a/faidx.c +++ b/faidx.c @@ -1,5 +1,4 @@ #include -#include #include #include #include @@ -85,14 +84,19 @@ faidx_t *fai_build_core(RAZF *rz) name[l_name++] = c; } name[l_name] = '\0'; - assert(ret); + if (ret == 0) { + fprintf(stderr, "[fai_build_core] the last entry has no sequence\n"); + free(name); fai_destroy(idx); + return 0; + } if (c != '\n') while (razf_read(rz, &c, 1) && c != '\n'); state = 1; len = 0; offset = razf_tell(rz); } else { if (state == 3) { - fprintf(stderr, "[fai_build_core] inlined empty line is not allowed in sequence '%s'. Abort!\n", name); - exit(1); + fprintf(stderr, "[fai_build_core] inlined empty line is not allowed in sequence '%s'.\n", name); + free(name); fai_destroy(idx); + return 0; } if (state == 2) state = 3; l1 = l2 = 0; @@ -101,13 +105,15 @@ faidx_t *fai_build_core(RAZF *rz) if (isgraph(c)) ++l2; } while ((ret = razf_read(rz, &c, 1)) && c != '\n'); if (state == 3 && l2) { - fprintf(stderr, "[fai_build_core] different line length in sequence '%s'. Abort!\n", name); - exit(1); + fprintf(stderr, "[fai_build_core] different line length in sequence '%s'.\n", name); + free(name); fai_destroy(idx); + return 0; } ++l1; len += l2; if (l2 >= 0x10000) { - fprintf(stderr, "[fai_build_core] line length exceeds 65535 in sequence '%s'. Abort!\n", name); - exit(1); + fprintf(stderr, "[fai_build_core] line length exceeds 65535 in sequence '%s'.\n", name); + free(name); fai_destroy(idx); + return 0; } if (state == 1) line_len = l1, line_blen = l2, state = 0; else if (state == 0) { @@ -161,7 +167,7 @@ void fai_destroy(faidx_t *fai) free(fai); } -void fai_build(const char *fn) +int fai_build(const char *fn) { char *str; RAZF *rz; @@ -170,15 +176,24 @@ void fai_build(const char *fn) str = (char*)calloc(strlen(fn) + 5, 1); sprintf(str, "%s.fai", fn); rz = razf_open(fn, "r"); - assert(rz); + if (rz == 0) { + fprintf(stderr, "[fai_build] fail to open the FASTA file.\n"); + free(str); + return -1; + } fai = fai_build_core(rz); razf_close(rz); fp = fopen(str, "w"); - assert(fp); + if (fp == 0) { + fprintf(stderr, "[fai_build] fail to write FASTA index.\n"); + fai_destroy(fai); free(str); + return -1; + } fai_save(fai, fp); fclose(fp); free(str); fai_destroy(fai); + return 0; } faidx_t *fai_load(const char *fn) @@ -194,6 +209,7 @@ faidx_t *fai_load(const char *fn) fai_build(fn); fp = fopen(str, "r"); if (fp == 0) { + fprintf(stderr, "[fai_load] fail to open FASTA index.\n"); free(str); return 0; } @@ -201,9 +217,11 @@ faidx_t *fai_load(const char *fn) fai = fai_read(fp); fclose(fp); fai->rz = razf_open(fn, "r"); - if (fai->rz == 0) return 0; - assert(fai->rz); free(str); + if (fai->rz == 0) { + fprintf(stderr, "[fai_load] fail to open FASTA file.\n"); + return 0; + } return fai; } @@ -271,7 +289,7 @@ int faidx_main(int argc, char *argv[]) char *s; faidx_t *fai; fai = fai_load(argv[1]); - assert(fai); + if (fai == 0) return 1; for (i = 2; i != argc; ++i) { printf(">%s\n", argv[i]); s = fai_fetch(fai, argv[i], &l); diff --git a/faidx.h b/faidx.h index 98c60e4..1a52fb7 100644 --- a/faidx.h +++ b/faidx.h @@ -46,9 +46,10 @@ extern "C" { /*! @abstract Build index for a FASTA or razip compressed FASTA file. @param fn FASTA file name + @return 0 on success; or -1 on failure @discussion File "fn.fai" will be generated. */ - void fai_build(const char *fn); + int fai_build(const char *fn); /*! @abstract Distroy a faidx_t struct. diff --git a/glf.c b/glf.c index 4a6c667..8d5346a 100644 --- a/glf.c +++ b/glf.c @@ -38,8 +38,9 @@ glf3_header_t *glf3_header_read(glfFile fp) h = glf3_header_init(); bgzf_read(fp, magic, 4); if (strncmp(magic, "GLF\3", 4)) { - fprintf(stderr, "[glf3_header_read] invalid magic. Abort.\n"); - exit(1); + fprintf(stderr, "[glf3_header_read] invalid magic.\n"); + glf3_header_destroy(h); + return 0; } bgzf_read(fp, &h->l_text, 4); if (glf3_is_BE) h->l_text = bam_swap_endian_4(h->l_text); -- 2.39.2