ed793e195478d944c19112fa4e0cb0884debdbb9 braney Sun Sep 16 08:33:51 2012 -0700 fix twoBit recognition logic (#9095). Look for signature in file rather than .2bit suffix diff --git src/lib/twoBit.c src/lib/twoBit.c index f01e2ea..10ec2e2 100644 --- src/lib/twoBit.c +++ src/lib/twoBit.c @@ -263,47 +263,62 @@ void twoBitClose(struct twoBitFile **pTbf) /* Free up resources associated with twoBitFile. */ { struct twoBitFile *tbf = *pTbf; if (tbf != NULL) { freez(&tbf->fileName); carefulClose(&tbf->f); hashFree(&tbf->hash); /* The indexList is allocated out of the hash's memory pool. */ bptFileClose(&tbf->bpt); freez(pTbf); } } +boolean twoBitSigRead(FILE *f, boolean *isSwapped) +/* read twoBit signature, return FALSE if not good + * set isSwapped to TRUE if twoBit file is byte swapped */ +{ +bits32 sig; + +*isSwapped = FALSE; +mustReadOne(f, sig); +if (sig == twoBitSwapSig) + *isSwapped = TRUE; +else if (sig != twoBitSig) + return FALSE; + +return TRUE; +} + static struct twoBitFile *twoBitOpenReadHeader(char *fileName) /* Open file, read in header but not index. * Squawk and die if there is a problem. */ { -bits32 sig; struct twoBitFile *tbf; boolean isSwapped = FALSE; FILE *f = mustOpen(fileName, "rb"); /* Allocate header verify signature, and read in * the constant-length bits. */ AllocVar(tbf); -mustReadOne(f, sig); -if (sig == twoBitSwapSig) - isSwapped = tbf->isSwapped = TRUE; -else if (sig != twoBitSig) + +if (!twoBitSigRead(f, &isSwapped)) errAbort("%s doesn't have a valid twoBitSig", fileName); + +tbf->isSwapped = isSwapped; tbf->fileName = cloneString(fileName); tbf->f = f; tbf->version = readBits32(f, isSwapped); if (tbf->version != 0) { errAbort("Can only handle version 0 of this file. This is version %d", (int)tbf->version); } tbf->seqCount = readBits32(f, isSwapped); tbf->reserved = readBits32(f, isSwapped); return tbf; } struct twoBitFile *twoBitOpen(char *fileName) /* Open file, read in header and index. @@ -758,31 +773,37 @@ struct twoBitIndex *index; struct slName *name, *list = NULL; for (index = tbf->indexList; index != NULL; index = index->next) { name = slNameNew(index->name); slAddHead(&list, name); } twoBitClose(&tbf); slReverse(&list); return list; } boolean twoBitIsFile(char *fileName) /* Return TRUE if file is in .2bit format. */ { -return endsWith(fileName, ".2bit"); +FILE *f = mustOpen(fileName, "rb"); +boolean isSwapped; +boolean isTwoBit = twoBitSigRead(f, &isSwapped); + +fclose(f); + +return isTwoBit; } boolean twoBitParseRange(char *rangeSpec, char **retFile, char **retSeq, int *retStart, int *retEnd) /* Parse out something in format * file/path/name:seqName:start-end * or * file/path/name:seqName * or * file/path/name:seqName1,seqName2,seqName3,... * This will destroy the input 'rangeSpec' in the process. Returns FALSE if * it doesn't fit this format, setting retFile to rangeSpec, and retSet to * null. If it is the shorter form then start and end will both be returned * as zero, which is ok by twoBitReadSeqFrag. Any of the return arguments * maybe NULL. @@ -921,30 +942,36 @@ if (s == NULL) s = spec->fileName; else s++; /* find end of file name and zero-terminate */ e = strchr(s, ':'); if (e == NULL) s = NULL; /* just file name */ else { *e++ = '\0'; s = e; } +if (!twoBitIsFile(spec->fileName)) + { + twoBitSpecFree(&spec); + return NULL; /* not a 2bit file */ + } + if (s != NULL) { /* chop seqs at commas and parse */ numSeqs = chopString(s, ",", NULL, 0); AllocArray(seqSpecs, numSeqs); chopString(s, ",", seqSpecs, numSeqs); for (i = 0; i< numSeqs; i++) slSafeAddHead(&spec->seqs, parseSeqSpec(seqSpecs[i])); slReverse(&spec->seqs); } return spec; } struct twoBitSpec *twoBitSpecNewFile(char *twoBitFile, char *specFile) /* parse a file containing a list of specifications for sequences in the