e020a087201d536e5ffe573fa6fb1ad1be68127c angie Wed Dec 18 16:54:56 2013 -0800 In MLQ #12367, the user got a blank screen when trying to view a CTusing a Mac-mangled BAM file. Of course we need to show an error message instead of SEGV/blank screen; but hgCustom also shouldn't have accepted the file as a custom track. It turns out that the samtools lib function samopen() may return a non-null file handler with a null header, when the header is invalid. So we need to check not only for null result from samopen, but also null header inside non-null result. Meanwhile, I noticed that hgCustom's error reporting was actually masking more detailed error messages from lib code, because of its use of errCatch around bamFileExists. errCatch only lets errAbort messages propagate, not warnings; bamFileExists has a warn() that is lost in transmission. I added bamFileAndIndexMustExist which uses errAbort so that errCatch in callers will get the more informative error instead of having to make up one of its own. trackHub checking code also needed this stronger form of checking. I also moved some duplicated (or triplicated) code in bamFile.c into functions. refs #12367 diff --git src/inc/bamFile.h src/inc/bamFile.h index c0392b9..94aa717 100644 --- src/inc/bamFile.h +++ src/inc/bamFile.h @@ -28,30 +28,34 @@ "(see http://genomewiki.ucsc.edu/index.php/Build_Environment_Variables)." #endif // USE_BAM struct bamChromInfo { struct bamChromInfo *next; char *name; /* Chromosome name */ bits32 size; /* Chromosome size in bases */ }; boolean bamFileExists(char *bamFileName); /* Return TRUE if we can successfully open the bam file and its index file. */ +void bamFileAndIndexMustExist(char *fileOrUrl); +/* Open both a bam file and its accompanying index or errAbort; this is what it + * takes for diagnostic info to propagate up through errCatches in calling code. */ + samfile_t *bamOpen(char *fileOrUrl, char **retBamFileName); /* Return an open bam file as well as the filename of the bam. */ void bamFetchAlreadyOpen(samfile_t *samfile, bam_index_t *idx, char *bamFileName, char *position, bam_fetch_f callbackFunc, void *callbackData); /* With the open bam file, return items the same way with the callbacks as with bamFetch() */ /* except in this case use an already-open bam file and index (use bam_index_load and free() for */ /* the index). It seems a little strange to pass the filename in with the open bam, but */ /* it's just used to report errors. */ void bamFetch(char *fileOrUrl, char *position, bam_fetch_f callbackFunc, void *callbackData, samfile_t **pSamFile); /* Open the .bam file, fetch items in the seq:start-end position range, * and call callbackFunc on each bam item retrieved from the file plus callbackData. * This handles BAM files with "chr"-less sequence names, e.g. from Ensembl.