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 <A HREF=\"http://genomewiki.ucsc.edu/index.php/Build_Environment_Variables\" " \
     "TARGET=_BLANK>http://genomewiki.ucsc.edu/index.php/Build_Environment_Variables</A>)."
 
 #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.