Coverage Report

Created: 2026-09-28 07:10

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/htslib/cram/cram_io.c
Line
Count
Source
1
/*
2
Copyright (c) 2012-2026 Genome Research Ltd.
3
Author: James Bonfield <jkb@sanger.ac.uk>
4
5
Redistribution and use in source and binary forms, with or without
6
modification, are permitted provided that the following conditions are met:
7
8
   1. Redistributions of source code must retain the above copyright notice,
9
this list of conditions and the following disclaimer.
10
11
   2. Redistributions in binary form must reproduce the above copyright notice,
12
this list of conditions and the following disclaimer in the documentation
13
and/or other materials provided with the distribution.
14
15
   3. Neither the names Genome Research Ltd and Wellcome Trust Sanger
16
Institute nor the names of its contributors may be used to endorse or promote
17
products derived from this software without specific prior written permission.
18
19
THIS SOFTWARE IS PROVIDED BY GENOME RESEARCH LTD AND CONTRIBUTORS "AS IS" AND
20
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
DISCLAIMED. IN NO EVENT SHALL GENOME RESEARCH LTD OR CONTRIBUTORS BE LIABLE
23
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
*/
30
31
/*
32
 * CRAM I/O primitives.
33
 *
34
 * - ITF8 encoding and decoding.
35
 * - Block based I/O
36
 * - Zlib inflating and deflating (memory)
37
 * - CRAM basic data structure reading and writing
38
 * - File opening / closing
39
 * - Reference sequence handling
40
 */
41
42
#define HTS_BUILDING_LIBRARY // Enables HTSLIB_EXPORT, see htslib/hts_defs.h
43
#include <config.h>
44
45
#include <stdio.h>
46
#include <errno.h>
47
#include <assert.h>
48
#include <stdlib.h>
49
#include <string.h>
50
#include <unistd.h>
51
#include <zlib.h>
52
#ifdef HAVE_LIBBZ2
53
#include <bzlib.h>
54
#endif
55
#ifdef HAVE_LIBLZMA
56
#ifdef HAVE_LZMA_H
57
#include <lzma.h>
58
#else
59
#include "../os/lzma_stub.h"
60
#endif
61
#endif
62
#include <sys/types.h>
63
#include <sys/stat.h>
64
#include <math.h>
65
#include <stdint.h>
66
67
#ifdef HAVE_LIBDEFLATE
68
#include <libdeflate.h>
69
#define crc32(a,b,c) libdeflate_crc32((a),(b),(c))
70
#endif
71
72
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
73
#include "../fuzz_settings.h"
74
#endif
75
76
#include "cram.h"
77
#include "os.h"
78
#include "../htslib/hts.h"
79
#include "../htslib/hts_alloc.h"
80
#include "../hts_internal.h"
81
#include "open_trace_file.h"
82
83
#if defined(HAVE_EXTERNAL_LIBHTSCODECS)
84
#include <htscodecs/rANS_static.h>
85
#include <htscodecs/rANS_static4x16.h>
86
#include <htscodecs/arith_dynamic.h>
87
#include <htscodecs/tokenise_name3.h>
88
#include <htscodecs/fqzcomp_qual.h>
89
#else
90
#include "../htscodecs/htscodecs/rANS_static.h"
91
#include "../htscodecs/htscodecs/rANS_static4x16.h"
92
#include "../htscodecs/htscodecs/arith_dynamic.h"
93
#include "../htscodecs/htscodecs/tokenise_name3.h"
94
#include "../htscodecs/htscodecs/fqzcomp_qual.h"
95
#include "../htscodecs/htscodecs/varint.h"
96
#endif
97
98
//#define REF_DEBUG
99
100
#ifdef REF_DEBUG
101
#include <sys/syscall.h>
102
#define gettid() (int)syscall(SYS_gettid)
103
104
#define RP(...) fprintf (stderr, __VA_ARGS__)
105
#else
106
#define RP(...)
107
#endif
108
109
#include "../htslib/hfile.h"
110
#include "../htslib/bgzf.h"
111
#include "../htslib/faidx.h"
112
#include "../hts_internal.h"
113
114
#ifndef PATH_MAX
115
#define PATH_MAX FILENAME_MAX
116
#endif
117
118
1.14M
#define TRIAL_SPAN 70
119
1.14M
#define NTRIALS 3
120
121
22.3k
#define CRAM_DEFAULT_LEVEL 5
122
123
/* ----------------------------------------------------------------------
124
 * ITF8 encoding and decoding.
125
 *
126
 * Also see the itf8_get and itf8_put macros in cram_io.h
127
 */
128
129
/*
130
 * LEGACY: consider using itf8_decode_crc.
131
 *
132
 * Reads an integer in ITF-8 encoding from 'cp' and stores it in
133
 * *val.
134
 *
135
 * Returns the number of bytes read on success
136
 *        -1 on failure
137
 */
138
0
int itf8_decode(cram_fd *fd, int32_t *val_p) {
139
0
    static int nbytes[16] = {
140
0
        0,0,0,0, 0,0,0,0,                               // 0000xxxx - 0111xxxx
141
0
        1,1,1,1,                                        // 1000xxxx - 1011xxxx
142
0
        2,2,                                            // 1100xxxx - 1101xxxx
143
0
        3,                                              // 1110xxxx
144
0
        4,                                              // 1111xxxx
145
0
    };
146
147
0
    static int nbits[16] = {
148
0
        0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, // 0000xxxx - 0111xxxx
149
0
        0x3f, 0x3f, 0x3f, 0x3f,                         // 1000xxxx - 1011xxxx
150
0
        0x1f, 0x1f,                                     // 1100xxxx - 1101xxxx
151
0
        0x0f,                                           // 1110xxxx
152
0
        0x0f,                                           // 1111xxxx
153
0
    };
154
155
0
    int32_t val = hgetc(fd->fp);
156
0
    if (val == -1)
157
0
        return -1;
158
159
0
    int i = nbytes[val>>4];
160
0
    val &= nbits[val>>4];
161
162
0
    switch(i) {
163
0
    case 0:
164
0
        *val_p = val;
165
0
        return 1;
166
167
0
    case 1:
168
0
        val = (val<<8) | (unsigned char)hgetc(fd->fp);
169
0
        *val_p = val;
170
0
        return 2;
171
172
0
    case 2:
173
0
        val = (val<<8) | (unsigned char)hgetc(fd->fp);
174
0
        val = (val<<8) | (unsigned char)hgetc(fd->fp);
175
0
        *val_p = val;
176
0
        return 3;
177
178
0
    case 3:
179
0
        val = (val<<8) | (unsigned char)hgetc(fd->fp);
180
0
        val = (val<<8) | (unsigned char)hgetc(fd->fp);
181
0
        val = (val<<8) | (unsigned char)hgetc(fd->fp);
182
0
        *val_p = val;
183
0
        return 4;
184
185
0
    case 4: // really 3.5 more, why make it different?
186
0
        val = (val<<8) | (unsigned char)hgetc(fd->fp);
187
0
        val = (val<<8) | (unsigned char)hgetc(fd->fp);
188
0
        val = (val<<8) | (unsigned char)hgetc(fd->fp);
189
0
        val = (val<<4) | (((unsigned char)hgetc(fd->fp)) & 0x0f);
190
0
        *val_p = val;
191
0
    }
192
193
0
    return 5;
194
0
}
195
196
460k
int itf8_decode_crc(cram_fd *fd, int32_t *val_p, uint32_t *crc) {
197
460k
    static int nbytes[16] = {
198
460k
        0,0,0,0, 0,0,0,0,                               // 0000xxxx - 0111xxxx
199
460k
        1,1,1,1,                                        // 1000xxxx - 1011xxxx
200
460k
        2,2,                                            // 1100xxxx - 1101xxxx
201
460k
        3,                                              // 1110xxxx
202
460k
        4,                                              // 1111xxxx
203
460k
    };
204
205
460k
    static int nbits[16] = {
206
460k
        0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, // 0000xxxx - 0111xxxx
207
460k
        0x3f, 0x3f, 0x3f, 0x3f,                         // 1000xxxx - 1011xxxx
208
460k
        0x1f, 0x1f,                                     // 1100xxxx - 1101xxxx
209
460k
        0x0f,                                           // 1110xxxx
210
460k
        0x0f,                                           // 1111xxxx
211
460k
    };
212
460k
    unsigned char c[5];
213
214
460k
    int32_t val = hgetc(fd->fp);
215
460k
    if (val == -1)
216
429
        return -1;
217
218
459k
    c[0]=val;
219
220
459k
    int i = nbytes[val>>4];
221
459k
    val &= nbits[val>>4];
222
223
459k
    if (i > 0) {
224
26.3k
        if (hread(fd->fp, &c[1], i) < i)
225
146
            return -1;
226
26.3k
    }
227
228
459k
    switch(i) {
229
433k
    case 0:
230
433k
        *val_p = val;
231
433k
        *crc = crc32(*crc, c, 1);
232
433k
        return 1;
233
234
11.9k
    case 1:
235
11.9k
        val = (val<<8) | c[1];
236
11.9k
        *val_p = val;
237
11.9k
        *crc = crc32(*crc, c, 2);
238
11.9k
        return 2;
239
240
6.96k
    case 2:
241
6.96k
        val = (val<<8) | c[1];
242
6.96k
        val = (val<<8) | c[2];
243
6.96k
        *val_p = val;
244
6.96k
        *crc = crc32(*crc, c, 3);
245
6.96k
        return 3;
246
247
1.43k
    case 3:
248
1.43k
        val = (val<<8) | c[1];
249
1.43k
        val = (val<<8) | c[2];
250
1.43k
        val = (val<<8) | c[3];
251
1.43k
        *val_p = val;
252
1.43k
        *crc = crc32(*crc, c, 4);
253
1.43k
        return 4;
254
255
5.84k
    case 4: // really 3.5 more, why make it different?
256
5.84k
        {
257
5.84k
            uint32_t uv = val;
258
5.84k
            uv = (uv<<8) |  c[1];
259
5.84k
            uv = (uv<<8) |  c[2];
260
5.84k
            uv = (uv<<8) |  c[3];
261
5.84k
            uv = (uv<<4) | (c[4] & 0x0f);
262
            // Avoid implementation-defined behaviour on negative values
263
5.84k
            *val_p = uv < 0x80000000UL ? (int32_t) uv : -((int32_t) (0xffffffffUL - uv)) - 1;
264
5.84k
            *crc = crc32(*crc, c, 5);
265
5.84k
        }
266
459k
    }
267
268
5.84k
    return 5;
269
459k
}
270
271
/*
272
 * Stores a value to memory in ITF-8 format.
273
 *
274
 * Returns the number of bytes required to store the number.
275
 * This is a maximum of 5 bytes.
276
 */
277
26.2M
static inline int itf8_put(char *cp, int32_t val) {
278
26.2M
    unsigned char *up = (unsigned char *)cp;
279
26.2M
    if        (!(val & ~0x00000007f)) { // 1 byte
280
25.2M
        *up = val;
281
25.2M
        return 1;
282
25.2M
    } else if (!(val & ~0x00003fff)) { // 2 byte
283
497k
        *up++ = (val >> 8 ) | 0x80;
284
497k
        *up   = val & 0xff;
285
497k
        return 2;
286
515k
    } else if (!(val & ~0x01fffff)) { // 3 byte
287
15.5k
        *up++ = (val >> 16) | 0xc0;
288
15.5k
        *up++ = (val >> 8 ) & 0xff;
289
15.5k
        *up   = val & 0xff;
290
15.5k
        return 3;
291
499k
    } else if (!(val & ~0x0fffffff)) { // 4 byte
292
311k
        *up++ = (val >> 24) | 0xe0;
293
311k
        *up++ = (val >> 16) & 0xff;
294
311k
        *up++ = (val >> 8 ) & 0xff;
295
311k
        *up   = val & 0xff;
296
311k
        return 4;
297
311k
    } else {                           // 5 byte
298
187k
        *up++ = 0xf0 | ((val>>28) & 0xff);
299
187k
        *up++ = (val >> 20) & 0xff;
300
187k
        *up++ = (val >> 12) & 0xff;
301
187k
        *up++ = (val >> 4 ) & 0xff;
302
187k
        *up = val & 0x0f;
303
187k
        return 5;
304
187k
    }
305
26.2M
}
306
307
308
/* 64-bit itf8 variant */
309
144k
static inline int ltf8_put(char *cp, int64_t val) {
310
144k
    unsigned char *up = (unsigned char *)cp;
311
144k
    if        (!(val & ~((1LL<<7)-1))) {
312
112k
        *up = val;
313
112k
        return 1;
314
112k
    } else if (!(val & ~((1LL<<(6+8))-1))) {
315
30.5k
        *up++ = (val >> 8 ) | 0x80;
316
30.5k
        *up   = val & 0xff;
317
30.5k
        return 2;
318
30.5k
    } else if (!(val & ~((1LL<<(5+2*8))-1))) {
319
1.82k
        *up++ = (val >> 16) | 0xc0;
320
1.82k
        *up++ = (val >> 8 ) & 0xff;
321
1.82k
        *up   = val & 0xff;
322
1.82k
        return 3;
323
1.82k
    } else if (!(val & ~((1LL<<(4+3*8))-1))) {
324
64
        *up++ = (val >> 24) | 0xe0;
325
64
        *up++ = (val >> 16) & 0xff;
326
64
        *up++ = (val >> 8 ) & 0xff;
327
64
        *up   = val & 0xff;
328
64
        return 4;
329
64
    } else if (!(val & ~((1LL<<(3+4*8))-1))) {
330
0
        *up++ = (val >> 32) | 0xf0;
331
0
        *up++ = (val >> 24) & 0xff;
332
0
        *up++ = (val >> 16) & 0xff;
333
0
        *up++ = (val >> 8 ) & 0xff;
334
0
        *up   = val & 0xff;
335
0
        return 5;
336
0
    } else if (!(val & ~((1LL<<(2+5*8))-1))) {
337
0
        *up++ = (val >> 40) | 0xf8;
338
0
        *up++ = (val >> 32) & 0xff;
339
0
        *up++ = (val >> 24) & 0xff;
340
0
        *up++ = (val >> 16) & 0xff;
341
0
        *up++ = (val >> 8 ) & 0xff;
342
0
        *up   = val & 0xff;
343
0
        return 6;
344
0
    } else if (!(val & ~((1LL<<(1+6*8))-1))) {
345
0
        *up++ = (val >> 48) | 0xfc;
346
0
        *up++ = (val >> 40) & 0xff;
347
0
        *up++ = (val >> 32) & 0xff;
348
0
        *up++ = (val >> 24) & 0xff;
349
0
        *up++ = (val >> 16) & 0xff;
350
0
        *up++ = (val >> 8 ) & 0xff;
351
0
        *up   = val & 0xff;
352
0
        return 7;
353
0
    } else if (!(val & ~((1LL<<(7*8))-1))) {
354
0
        *up++ = (val >> 56) | 0xfe;
355
0
        *up++ = (val >> 48) & 0xff;
356
0
        *up++ = (val >> 40) & 0xff;
357
0
        *up++ = (val >> 32) & 0xff;
358
0
        *up++ = (val >> 24) & 0xff;
359
0
        *up++ = (val >> 16) & 0xff;
360
0
        *up++ = (val >> 8 ) & 0xff;
361
0
        *up   = val & 0xff;
362
0
        return 8;
363
0
    } else {
364
0
        *up++ = 0xff;
365
0
        *up++ = (val >> 56) & 0xff;
366
0
        *up++ = (val >> 48) & 0xff;
367
0
        *up++ = (val >> 40) & 0xff;
368
0
        *up++ = (val >> 32) & 0xff;
369
0
        *up++ = (val >> 24) & 0xff;
370
0
        *up++ = (val >> 16) & 0xff;
371
0
        *up++ = (val >> 8 ) & 0xff;
372
0
        *up   = val & 0xff;
373
0
        return 9;
374
0
    }
375
144k
}
376
377
/*
378
 * Encodes and writes a single integer in ITF-8 format.
379
 * Returns 0 on success
380
 *        -1 on failure
381
 */
382
0
int itf8_encode(cram_fd *fd, int32_t val) {
383
0
    char buf[5];
384
0
    int len = itf8_put(buf, val);
385
0
    return hwrite(fd->fp, buf, len) == len ? 0 : -1;
386
0
}
387
388
const int itf8_bytes[16] = {
389
    1, 1, 1, 1,  1, 1, 1, 1,
390
    2, 2, 2, 2,  3, 3, 4, 5
391
};
392
393
const int ltf8_bytes[256] = {
394
    1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
395
    1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
396
    1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
397
    1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
398
399
    1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
400
    1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
401
    1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
402
    1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,  1, 1, 1, 1,
403
404
    2, 2, 2, 2,  2, 2, 2, 2,  2, 2, 2, 2,  2, 2, 2, 2,
405
    2, 2, 2, 2,  2, 2, 2, 2,  2, 2, 2, 2,  2, 2, 2, 2,
406
    2, 2, 2, 2,  2, 2, 2, 2,  2, 2, 2, 2,  2, 2, 2, 2,
407
    2, 2, 2, 2,  2, 2, 2, 2,  2, 2, 2, 2,  2, 2, 2, 2,
408
409
    3, 3, 3, 3,  3, 3, 3, 3,  3, 3, 3, 3,  3, 3, 3, 3,
410
    3, 3, 3, 3,  3, 3, 3, 3,  3, 3, 3, 3,  3, 3, 3, 3,
411
412
    4, 4, 4, 4,  4, 4, 4, 4,  4, 4, 4, 4,  4, 4, 4, 4,
413
414
    5, 5, 5, 5,  5, 5, 5, 5,  6, 6, 6, 6,  7, 7, 8, 9
415
};
416
417
/*
418
 * LEGACY: consider using ltf8_decode_crc.
419
 */
420
0
int ltf8_decode(cram_fd *fd, int64_t *val_p) {
421
0
    int c = hgetc(fd->fp);
422
0
    int64_t val = (unsigned char)c;
423
0
    if (c == -1)
424
0
        return -1;
425
426
0
    if (val < 0x80) {
427
0
        *val_p =   val;
428
0
        return 1;
429
430
0
    } else if (val < 0xc0) {
431
0
        val = (val<<8) | (unsigned char)hgetc(fd->fp);
432
0
        *val_p = val & (((1LL<<(6+8)))-1);
433
0
        return 2;
434
435
0
    } else if (val < 0xe0) {
436
0
        val = (val<<8) | (unsigned char)hgetc(fd->fp);
437
0
        val = (val<<8) | (unsigned char)hgetc(fd->fp);
438
0
        *val_p = val & ((1LL<<(5+2*8))-1);
439
0
        return 3;
440
441
0
    } else if (val < 0xf0) {
442
0
        val = (val<<8) | (unsigned char)hgetc(fd->fp);
443
0
        val = (val<<8) | (unsigned char)hgetc(fd->fp);
444
0
        val = (val<<8) | (unsigned char)hgetc(fd->fp);
445
0
        *val_p = val & ((1LL<<(4+3*8))-1);
446
0
        return 4;
447
448
0
    } else if (val < 0xf8) {
449
0
        val = (val<<8) | (unsigned char)hgetc(fd->fp);
450
0
        val = (val<<8) | (unsigned char)hgetc(fd->fp);
451
0
        val = (val<<8) | (unsigned char)hgetc(fd->fp);
452
0
        val = (val<<8) | (unsigned char)hgetc(fd->fp);
453
0
        *val_p = val & ((1LL<<(3+4*8))-1);
454
0
        return 5;
455
456
0
    } else if (val < 0xfc) {
457
0
        val = (val<<8) | (unsigned char)hgetc(fd->fp);
458
0
        val = (val<<8) | (unsigned char)hgetc(fd->fp);
459
0
        val = (val<<8) | (unsigned char)hgetc(fd->fp);
460
0
        val = (val<<8) | (unsigned char)hgetc(fd->fp);
461
0
        val = (val<<8) | (unsigned char)hgetc(fd->fp);
462
0
        *val_p = val & ((1LL<<(2+5*8))-1);
463
0
        return 6;
464
465
0
    } else if (val < 0xfe) {
466
0
        val = (val<<8) | (unsigned char)hgetc(fd->fp);
467
0
        val = (val<<8) | (unsigned char)hgetc(fd->fp);
468
0
        val = (val<<8) | (unsigned char)hgetc(fd->fp);
469
0
        val = (val<<8) | (unsigned char)hgetc(fd->fp);
470
0
        val = (val<<8) | (unsigned char)hgetc(fd->fp);
471
0
        val = (val<<8) | (unsigned char)hgetc(fd->fp);
472
0
        *val_p = val & ((1LL<<(1+6*8))-1);
473
0
        return 7;
474
475
0
    } else if (val < 0xff) {
476
0
        val = (val<<8) | (unsigned char)hgetc(fd->fp);
477
0
        val = (val<<8) | (unsigned char)hgetc(fd->fp);
478
0
        val = (val<<8) | (unsigned char)hgetc(fd->fp);
479
0
        val = (val<<8) | (unsigned char)hgetc(fd->fp);
480
0
        val = (val<<8) | (unsigned char)hgetc(fd->fp);
481
0
        val = (val<<8) | (unsigned char)hgetc(fd->fp);
482
0
        val = (val<<8) | (unsigned char)hgetc(fd->fp);
483
0
        *val_p = val & ((1LL<<(7*8))-1);
484
0
        return 8;
485
486
0
    } else {
487
0
        val = (val<<8) | (unsigned char)hgetc(fd->fp);
488
0
        val = (val<<8) | (unsigned char)hgetc(fd->fp);
489
0
        val = (val<<8) | (unsigned char)hgetc(fd->fp);
490
0
        val = (val<<8) | (unsigned char)hgetc(fd->fp);
491
0
        val = (val<<8) | (unsigned char)hgetc(fd->fp);
492
0
        val = (val<<8) | (unsigned char)hgetc(fd->fp);
493
0
        val = (val<<8) | (unsigned char)hgetc(fd->fp);
494
0
        val = (val<<8) | (unsigned char)hgetc(fd->fp);
495
0
        *val_p = val;
496
0
    }
497
498
0
    return 9;
499
0
}
500
501
16.8k
int ltf8_decode_crc(cram_fd *fd, int64_t *val_p, uint32_t *crc) {
502
16.8k
    unsigned char c[9];
503
16.8k
    int64_t val = hgetc(fd->fp);
504
16.8k
    if (val < 0)
505
13
        return -1;
506
507
16.8k
    c[0] = val;
508
509
16.8k
    if (val < 0x80) {
510
15.3k
        *val_p =   val;
511
15.3k
        *crc = crc32(*crc, c, 1);
512
15.3k
        return 1;
513
514
15.3k
    } else if (val < 0xc0) {
515
288
        int v = hgetc(fd->fp);
516
288
        if (v < 0)
517
13
            return -1;
518
275
        val = (val<<8) | (c[1]=v);
519
275
        *val_p = val & (((1LL<<(6+8)))-1);
520
275
        *crc = crc32(*crc, c, 2);
521
275
        return 2;
522
523
1.24k
    } else if (val < 0xe0) {
524
213
        if (hread(fd->fp, &c[1], 2) < 2)
525
8
            return -1;
526
205
        val = (val<<8) | c[1];
527
205
        val = (val<<8) | c[2];
528
205
        *val_p = val & ((1LL<<(5+2*8))-1);
529
205
        *crc = crc32(*crc, c, 3);
530
205
        return 3;
531
532
1.03k
    } else if (val < 0xf0) {
533
155
        if (hread(fd->fp, &c[1], 3) < 3)
534
5
            return -1;
535
150
        val = (val<<8) | c[1];
536
150
        val = (val<<8) | c[2];
537
150
        val = (val<<8) | c[3];
538
150
        *val_p = val & ((1LL<<(4+3*8))-1);
539
150
        *crc = crc32(*crc, c, 4);
540
150
        return 4;
541
542
878
    } else if (val < 0xf8) {
543
310
        if (hread(fd->fp, &c[1], 4) < 4)
544
5
            return -1;
545
305
        val = (val<<8) | c[1];
546
305
        val = (val<<8) | c[2];
547
305
        val = (val<<8) | c[3];
548
305
        val = (val<<8) | c[4];
549
305
        *val_p = val & ((1LL<<(3+4*8))-1);
550
305
        *crc = crc32(*crc, c, 5);
551
305
        return 5;
552
553
568
    } else if (val < 0xfc) {
554
153
        if (hread(fd->fp, &c[1], 5) < 5)
555
9
            return -1;
556
144
        val = (val<<8) | c[1];
557
144
        val = (val<<8) | c[2];
558
144
        val = (val<<8) | c[3];
559
144
        val = (val<<8) | c[4];
560
144
        val = (val<<8) | c[5];
561
144
        *val_p = val & ((1LL<<(2+5*8))-1);
562
144
        *crc = crc32(*crc, c, 6);
563
144
        return 6;
564
565
415
    } else if (val < 0xfe) {
566
132
        if (hread(fd->fp, &c[1], 6) < 6)
567
8
            return -1;
568
124
        val = (val<<8) | c[1];
569
124
        val = (val<<8) | c[2];
570
124
        val = (val<<8) | c[3];
571
124
        val = (val<<8) | c[4];
572
124
        val = (val<<8) | c[5];
573
124
        val = (val<<8) | c[6];
574
124
        *val_p = val & ((1LL<<(1+6*8))-1);
575
124
        *crc = crc32(*crc, c, 7);
576
124
        return 7;
577
578
283
    } else if (val < 0xff) {
579
80
        uint64_t uval = val;
580
80
        if (hread(fd->fp, &c[1], 7) < 7)
581
5
            return -1;
582
75
        uval = (uval<<8) | c[1];
583
75
        uval = (uval<<8) | c[2];
584
75
        uval = (uval<<8) | c[3];
585
75
        uval = (uval<<8) | c[4];
586
75
        uval = (uval<<8) | c[5];
587
75
        uval = (uval<<8) | c[6];
588
75
        uval = (uval<<8) | c[7];
589
75
        *val_p = uval & ((1ULL<<(7*8))-1);
590
75
        *crc = crc32(*crc, c, 8);
591
75
        return 8;
592
593
203
    } else {
594
203
        uint64_t uval;
595
203
        if (hread(fd->fp, &c[1], 8) < 8)
596
19
            return -1;
597
184
        uval =             c[1];
598
184
        uval = (uval<<8) | c[2];
599
184
        uval = (uval<<8) | c[3];
600
184
        uval = (uval<<8) | c[4];
601
184
        uval = (uval<<8) | c[5];
602
184
        uval = (uval<<8) | c[6];
603
184
        uval = (uval<<8) | c[7];
604
184
        uval = (uval<<8) | c[8];
605
184
        *crc = crc32(*crc, c, 9);
606
        // Avoid implementation-defined behaviour on negative values
607
184
        *val_p = c[1] < 0x80 ? (int64_t) uval : -((int64_t) (0xffffffffffffffffULL - uval)) - 1;
608
184
    }
609
610
184
    return 9;
611
16.8k
}
612
613
/*
614
 * Pushes a value in ITF8 format onto the end of a block.
615
 * This shouldn't be used for high-volume data as it is not the fastest
616
 * method.
617
 *
618
 * Returns the number of bytes written
619
 */
620
21.2M
int itf8_put_blk(cram_block *blk, int32_t val) {
621
21.2M
    char buf[5];
622
21.2M
    int sz;
623
624
21.2M
    sz = itf8_put(buf, val);
625
21.2M
    BLOCK_APPEND(blk, buf, sz);
626
21.2M
    return sz;
627
628
0
 block_err:
629
0
    return -1;
630
21.2M
}
631
632
0
int ltf8_put_blk(cram_block *blk, int64_t val) {
633
0
    char buf[9];
634
0
    int sz;
635
636
0
    sz = ltf8_put(buf, val);
637
0
    BLOCK_APPEND(blk, buf, sz);
638
0
    return sz;
639
640
0
 block_err:
641
0
    return -1;
642
0
}
643
644
451k
static int64_t safe_itf8_get(char **cp, const char *endp, int *err) {
645
451k
    const unsigned char *up = (unsigned char *)*cp;
646
647
451k
    if (endp && endp - *cp < 5 &&
648
194k
        (*cp >= endp || endp - *cp < itf8_bytes[up[0]>>4])) {
649
187k
        if (err) *err = 1;
650
187k
        return 0;
651
187k
    }
652
653
263k
    if (up[0] < 0x80) {
654
241k
        (*cp)++;
655
241k
        return up[0];
656
241k
    } else if (up[0] < 0xc0) {
657
8.54k
        (*cp)+=2;
658
8.54k
        return ((up[0] <<8) |  up[1])                           & 0x3fff;
659
13.7k
    } else if (up[0] < 0xe0) {
660
3.76k
        (*cp)+=3;
661
3.76k
        return ((up[0]<<16) | (up[1]<< 8) |  up[2])             & 0x1fffff;
662
9.99k
    } else if (up[0] < 0xf0) {
663
2.49k
        (*cp)+=4;
664
2.49k
        uint32_t uv = (((uint32_t)up[0]<<24) | (up[1]<<16) | (up[2]<<8) | up[3]) & 0x0fffffff;
665
2.49k
        return (int32_t)uv;
666
7.50k
    } else {
667
7.50k
        (*cp)+=5;
668
7.50k
        uint32_t uv = (((uint32_t)up[0] & 0x0f)<<28) | (up[1]<<20) | (up[2]<<12) | (up[3]<<4) | (up[4] & 0x0f);
669
7.50k
        return (int32_t)uv;
670
7.50k
    }
671
263k
}
672
673
0
static int64_t safe_ltf8_get(char **cp, const char *endp, int *err) {
674
0
    unsigned char *up = (unsigned char *)*cp;
675
676
0
    if (endp && endp - *cp < 9 &&
677
0
        (*cp >= endp || endp - *cp < ltf8_bytes[up[0]])) {
678
0
        if (err) *err = 1;
679
0
        return 0;
680
0
    }
681
682
0
    if (up[0] < 0x80) {
683
0
        (*cp)++;
684
0
        return up[0];
685
0
    } else if (up[0] < 0xc0) {
686
0
        (*cp)+=2;
687
0
        return (((uint64_t)up[0]<< 8) |
688
0
                 (uint64_t)up[1]) & (((1LL<<(6+8)))-1);
689
0
    } else if (up[0] < 0xe0) {
690
0
        (*cp)+=3;
691
0
        return (((uint64_t)up[0]<<16) |
692
0
                ((uint64_t)up[1]<< 8) |
693
0
                 (uint64_t)up[2]) & ((1LL<<(5+2*8))-1);
694
0
    } else if (up[0] < 0xf0) {
695
0
        (*cp)+=4;
696
0
        return (((uint64_t)up[0]<<24) |
697
0
                ((uint64_t)up[1]<<16) |
698
0
                ((uint64_t)up[2]<< 8) |
699
0
                 (uint64_t)up[3]) & ((1LL<<(4+3*8))-1);
700
0
    } else if (up[0] < 0xf8) {
701
0
        (*cp)+=5;
702
0
        return (((uint64_t)up[0]<<32) |
703
0
                ((uint64_t)up[1]<<24) |
704
0
                ((uint64_t)up[2]<<16) |
705
0
                ((uint64_t)up[3]<< 8) |
706
0
                 (uint64_t)up[4]) & ((1LL<<(3+4*8))-1);
707
0
    } else if (up[0] < 0xfc) {
708
0
        (*cp)+=6;
709
0
        return (((uint64_t)up[0]<<40) |
710
0
                ((uint64_t)up[1]<<32) |
711
0
                ((uint64_t)up[2]<<24) |
712
0
                ((uint64_t)up[3]<<16) |
713
0
                ((uint64_t)up[4]<< 8) |
714
0
                 (uint64_t)up[5]) & ((1LL<<(2+5*8))-1);
715
0
    } else if (up[0] < 0xfe) {
716
0
        (*cp)+=7;
717
0
        return (((uint64_t)up[0]<<48) |
718
0
                ((uint64_t)up[1]<<40) |
719
0
                ((uint64_t)up[2]<<32) |
720
0
                ((uint64_t)up[3]<<24) |
721
0
                ((uint64_t)up[4]<<16) |
722
0
                ((uint64_t)up[5]<< 8) |
723
0
                 (uint64_t)up[6]) & ((1LL<<(1+6*8))-1);
724
0
    } else if (up[0] < 0xff) {
725
0
        (*cp)+=8;
726
0
        return (((uint64_t)up[1]<<48) |
727
0
                ((uint64_t)up[2]<<40) |
728
0
                ((uint64_t)up[3]<<32) |
729
0
                ((uint64_t)up[4]<<24) |
730
0
                ((uint64_t)up[5]<<16) |
731
0
                ((uint64_t)up[6]<< 8) |
732
0
                 (uint64_t)up[7]) & ((1LL<<(7*8))-1);
733
0
    } else {
734
0
        (*cp)+=9;
735
0
        return (((uint64_t)up[1]<<56) |
736
0
                ((uint64_t)up[2]<<48) |
737
0
                ((uint64_t)up[3]<<40) |
738
0
                ((uint64_t)up[4]<<32) |
739
0
                ((uint64_t)up[5]<<24) |
740
0
                ((uint64_t)up[6]<<16) |
741
0
                ((uint64_t)up[7]<< 8) |
742
0
                 (uint64_t)up[8]);
743
0
    }
744
0
}
745
746
// Wrapper for now
747
5.02M
static int safe_itf8_put(char *cp, char *cp_end, int32_t val) {
748
5.02M
    return itf8_put(cp, val);
749
5.02M
}
750
751
144k
static int safe_ltf8_put(char *cp, char *cp_end, int64_t val) {
752
144k
    return ltf8_put(cp, val);
753
144k
}
754
755
1.14M
static int itf8_size(int64_t v) {
756
1.14M
    return ((!((v)&~0x7f))?1:(!((v)&~0x3fff))?2:(!((v)&~0x1fffff))?3:(!((v)&~0xfffffff))?4:5);
757
1.14M
}
758
759
//-----------------------------------------------------------------------------
760
761
/*
762
 * Decodes a 32-bit little endian value from fd and stores in val.
763
 *
764
 * Returns the number of bytes read on success
765
 *         -1 on failure
766
 */
767
21.6k
static int int32_decode(cram_fd *fd, int32_t *val) {
768
21.6k
    int32_t i;
769
21.6k
    if (4 != hread(fd->fp, &i, 4))
770
36
        return -1;
771
772
21.6k
    *val = le_int4(i);
773
21.6k
    return 4;
774
21.6k
}
775
776
/*
777
 * Encodes a 32-bit little endian value 'val' and writes to fd.
778
 *
779
 * Returns the number of bytes written on success
780
 *         -1 on failure
781
 */
782
302k
static int int32_encode(cram_fd *fd, int32_t val) {
783
302k
    uint32_t v = le_int4(val);
784
302k
    if (4 != hwrite(fd->fp, &v, 4))
785
0
        return -1;
786
787
302k
    return 4;
788
302k
}
789
790
/* As int32_decoded/encode, but from/to blocks instead of cram_fd */
791
417
int int32_get_blk(cram_block *b, int32_t *val) {
792
417
    if (b->uncomp_size - BLOCK_SIZE(b) < 4)
793
57
        return -1;
794
795
360
    uint32_t v =
796
360
         ((uint32_t) b->data[b->byte  ])        |
797
360
        (((uint32_t) b->data[b->byte+1]) <<  8) |
798
360
        (((uint32_t) b->data[b->byte+2]) << 16) |
799
360
        (((uint32_t) b->data[b->byte+3]) << 24);
800
    // Avoid implementation-defined behaviour on negative values
801
360
    *val = v < 0x80000000U ? (int32_t) v : -((int32_t) (0xffffffffU - v)) - 1;
802
360
    BLOCK_SIZE(b) += 4;
803
360
    return 4;
804
417
}
805
806
/* As int32_decoded/encode, but from/to blocks instead of cram_fd */
807
10.2k
int int32_put_blk(cram_block *b, int32_t val) {
808
10.2k
    unsigned char cp[4];
809
10.2k
    uint32_t v = val;
810
10.2k
    cp[0] = ( v      & 0xff);
811
10.2k
    cp[1] = ((v>>8)  & 0xff);
812
10.2k
    cp[2] = ((v>>16) & 0xff);
813
10.2k
    cp[3] = ((v>>24) & 0xff);
814
815
10.2k
    BLOCK_APPEND(b, cp, 4);
816
10.2k
    return 0;
817
818
0
 block_err:
819
0
    return -1;
820
10.2k
}
821
822
#ifdef HAVE_LIBDEFLATE
823
/* ----------------------------------------------------------------------
824
 * libdeflate compression code, with interface to match
825
 * zlib_mem_{in,de}flate for simplicity elsewhere.
826
 */
827
828
// Named the same as the version that uses zlib as we always use libdeflate for
829
// decompression when available.
830
static char *zlib_mem_inflate(char *cdata, size_t csize, size_t *size) {
831
    struct libdeflate_decompressor *z = libdeflate_alloc_decompressor();
832
    if (!z) {
833
        hts_log_error("Call to libdeflate_alloc_decompressor failed");
834
        return NULL;
835
    }
836
837
    assert (*size > 0);
838
    uint8_t *data = malloc(*size);
839
    if (!data) {
840
        hts_log_error("Memory allocation failure");
841
        goto fail;
842
    }
843
844
845
    int ret = libdeflate_gzip_decompress(z, cdata, csize, data, *size, size);
846
847
    if (ret != LIBDEFLATE_SUCCESS) {
848
        hts_log_error("Inflate operation failed: %d", ret);
849
        goto fail;
850
    }
851
852
    libdeflate_free_decompressor(z);
853
    return (char *)data;
854
855
 fail:
856
    libdeflate_free_decompressor(z);
857
    free(data);
858
    return NULL;
859
}
860
861
// Named differently as we use both zlib/libdeflate for compression.
862
static char *libdeflate_deflate(char *data, size_t size, size_t *cdata_size,
863
                                int level, int strat) {
864
    level = level > 0 ? level : 6; // libdeflate doesn't honour -1 as default
865
    level *= 1.23;     // NB levels go up to 12 here; 5 onwards is +1
866
    level += level>=8; // 5,6,7->6,7,8  8->10  9->12
867
    if (level > 12) level = 12;
868
869
    if (strat == Z_RLE) // not supported by libdeflate
870
        level = 1;
871
872
    struct libdeflate_compressor *z = libdeflate_alloc_compressor(level);
873
    if (!z) {
874
        hts_log_error("Call to libdeflate_alloc_compressor failed");
875
        return NULL;
876
    }
877
878
    unsigned char *cdata = NULL; /* Compressed output */
879
    size_t cdata_alloc;
880
    cdata = malloc(cdata_alloc = size*1.05+100);
881
    if (!cdata) {
882
        hts_log_error("Memory allocation failure");
883
        libdeflate_free_compressor(z);
884
        return NULL;
885
    }
886
887
    *cdata_size = libdeflate_gzip_compress(z, data, size, cdata, cdata_alloc);
888
    libdeflate_free_compressor(z);
889
890
    if (*cdata_size == 0) {
891
        hts_log_error("Call to libdeflate_gzip_compress failed");
892
        free(cdata);
893
        return NULL;
894
    }
895
896
    return (char *)cdata;
897
}
898
899
#else
900
901
/* ----------------------------------------------------------------------
902
 * zlib compression code - from Gap5's tg_iface_g.c
903
 * They're static here as they're only used within the cram_compress_block
904
 * and cram_uncompress_block functions, which are the external interface.
905
 */
906
16
char *zlib_mem_inflate(char *cdata, size_t csize, size_t *size) {
907
16
    z_stream s;
908
16
    unsigned char *data = NULL; /* Uncompressed output */
909
16
    int err;
910
911
16
    assert(*size > 0);
912
    // These should always be true due to type of cram_block::comp_size
913
    // and cram_block::uncomp_size
914
16
    assert(*size < UINT_MAX);
915
16
    assert(csize < UINT_MAX);
916
16
    data = malloc(*size);
917
16
    if (!data)
918
0
        return NULL;
919
920
    /* Initialise zlib stream */
921
16
    s.zalloc = Z_NULL; /* use default allocation functions */
922
16
    s.zfree  = Z_NULL;
923
16
    s.msg    = Z_NULL;
924
16
    s.opaque = Z_NULL;
925
16
    s.next_in  = (unsigned char *)cdata;
926
16
    s.avail_in = (uInt) csize;
927
16
    s.total_in = 0;
928
16
    s.next_out  = data;
929
16
    s.avail_out = (uInt) *size;
930
16
    s.total_out = 0;
931
932
    //err = inflateInit(&s);
933
16
    err = inflateInit2(&s, 15 + 32);
934
16
    if (err != Z_OK) {
935
0
        hts_log_error("Call to zlib inflateInit failed: %s", s.msg);
936
0
        free(data);
937
0
        return NULL;
938
0
    }
939
940
    /* Decode to 'data' array */
941
16
    err = inflate(&s, Z_FINISH);
942
943
16
    if (err != Z_STREAM_END) {
944
16
        hts_log_error("Call to zlib inflate failed: %s",
945
16
                      err != Z_OK ? s.msg : "not enough data");
946
16
        free(data);
947
16
        inflateEnd(&s);
948
16
        return NULL;
949
16
    }
950
951
0
    inflateEnd(&s);
952
953
0
    *size = s.total_out;
954
0
    return (char *)data;
955
16
}
956
#endif
957
958
#if !defined(HAVE_LIBDEFLATE) || LIBDEFLATE_VERSION_MAJOR < 1 || (LIBDEFLATE_VERSION_MAJOR ==  1 && LIBDEFLATE_VERSION_MINOR <= 8)
959
static char *zlib_mem_deflate(char *data, size_t size, size_t *cdata_size,
960
295k
                              int level, int strat) {
961
295k
    z_stream s;
962
295k
    unsigned char *cdata = NULL; /* Compressed output */
963
295k
    int cdata_alloc = 0;
964
295k
    int cdata_pos = 0;
965
295k
    int err;
966
967
295k
    cdata = malloc(cdata_alloc = size*1.05+100);
968
295k
    if (!cdata)
969
0
        return NULL;
970
295k
    cdata_pos = 0;
971
972
    /* Initialise zlib stream */
973
295k
    s.zalloc = Z_NULL; /* use default allocation functions */
974
295k
    s.zfree  = Z_NULL;
975
295k
    s.opaque = Z_NULL;
976
295k
    s.next_in  = (unsigned char *)data;
977
295k
    s.avail_in = size;
978
295k
    s.total_in = 0;
979
295k
    s.next_out  = cdata;
980
295k
    s.avail_out = cdata_alloc;
981
295k
    s.total_out = 0;
982
295k
    s.data_type = Z_BINARY;
983
984
295k
    err = deflateInit2(&s, level, Z_DEFLATED, 15|16, 9, strat);
985
295k
    if (err != Z_OK) {
986
0
        hts_log_error("Call to zlib deflateInit2 failed: %s", s.msg);
987
0
        return NULL;
988
0
    }
989
990
    /* Encode to 'cdata' array */
991
590k
    for (;s.avail_in;) {
992
295k
        s.next_out = &cdata[cdata_pos];
993
295k
        s.avail_out = cdata_alloc - cdata_pos;
994
295k
        if (cdata_alloc - cdata_pos <= 0) {
995
0
            hts_log_error("Deflate produced larger output than expected");
996
0
            return NULL;
997
0
        }
998
295k
        err = deflate(&s, Z_NO_FLUSH);
999
295k
        cdata_pos = cdata_alloc - s.avail_out;
1000
295k
        if (err != Z_OK) {
1001
0
            hts_log_error("Call to zlib deflate failed: %s", s.msg);
1002
0
            break;
1003
0
        }
1004
295k
    }
1005
295k
    if (deflate(&s, Z_FINISH) != Z_STREAM_END) {
1006
0
        hts_log_error("Call to zlib deflate failed: %s", s.msg);
1007
0
    }
1008
295k
    *cdata_size = s.total_out;
1009
1010
295k
    if (deflateEnd(&s) != Z_OK) {
1011
0
        hts_log_error("Call to zlib deflate failed: %s", s.msg);
1012
0
    }
1013
295k
    return (char *)cdata;
1014
295k
}
1015
#endif
1016
1017
#ifdef HAVE_LIBLZMA
1018
/* ------------------------------------------------------------------------ */
1019
/*
1020
 * Data compression routines using liblzma (xz)
1021
 *
1022
 * On a test set this shrunk the main db from 136157104 bytes to 114796168, but
1023
 * caused tg_index to grow from 2m43.707s to 15m3.961s. Exporting as bfastq
1024
 * went from 18.3s to 36.3s. So decompression suffers too, but not as bad
1025
 * as compression times.
1026
 *
1027
 * For now we disable this functionality. If it's to be re-enabled make sure you
1028
 * improve the mem_inflate implementation as it's just a test hack at the
1029
 * moment.
1030
 */
1031
1032
static char *lzma_mem_deflate(char *data, size_t size, size_t *cdata_size,
1033
0
                              int level) {
1034
0
    char *out;
1035
0
    size_t out_size = lzma_stream_buffer_bound(size);
1036
0
    *cdata_size = 0;
1037
1038
0
    out = malloc(out_size);
1039
1040
    /* Single call compression */
1041
0
    if (LZMA_OK != lzma_easy_buffer_encode(level, LZMA_CHECK_CRC32, NULL,
1042
0
                                           (uint8_t *)data, size,
1043
0
                                           (uint8_t *)out, cdata_size,
1044
0
                                           out_size))
1045
0
        return NULL;
1046
1047
0
    return out;
1048
0
}
1049
1050
10
static char *lzma_mem_inflate(char *cdata, size_t csize, size_t *size) {
1051
10
    lzma_stream strm = LZMA_STREAM_INIT;
1052
10
    size_t out_size = 0, out_pos = 0;
1053
10
    char *out = NULL, *new_out;
1054
10
    int r;
1055
1056
    /* Initiate the decoder */
1057
10
    if (LZMA_OK != lzma_stream_decoder(&strm, lzma_easy_decoder_memusage(9), 0))
1058
0
        return NULL;
1059
1060
    /* Decode loop */
1061
10
    strm.avail_in = csize;
1062
10
    strm.next_in = (uint8_t *)cdata;
1063
1064
14
    for (;strm.avail_in;) {
1065
8
        if (strm.avail_in > out_size - out_pos) {
1066
8
            out_size += strm.avail_in * 4 + 32768;
1067
8
            new_out = realloc(out, out_size);
1068
8
            if (!new_out)
1069
0
                goto fail;
1070
8
            out = new_out;
1071
8
        }
1072
8
        strm.avail_out = out_size - out_pos;
1073
8
        strm.next_out = (uint8_t *)&out[out_pos];
1074
1075
8
        r = lzma_code(&strm, LZMA_RUN);
1076
8
        if (LZMA_OK != r && LZMA_STREAM_END != r) {
1077
4
            hts_log_error("LZMA decode failure (error %d)", r);
1078
4
            goto fail;
1079
4
        }
1080
1081
4
        out_pos = strm.total_out;
1082
1083
4
        if (r == LZMA_STREAM_END)
1084
0
            break;
1085
4
    }
1086
1087
    /* finish up any unflushed data; necessary? */
1088
6
    r = lzma_code(&strm, LZMA_FINISH);
1089
6
    if (r != LZMA_OK && r != LZMA_STREAM_END) {
1090
0
        hts_log_error("Call to lzma_code failed with error %d", r);
1091
0
        goto fail;
1092
0
    }
1093
1094
6
    new_out = realloc(out, strm.total_out > 0 ? strm.total_out : 1);
1095
6
    if (new_out)
1096
6
        out = new_out;
1097
6
    *size = strm.total_out;
1098
1099
6
    lzma_end(&strm);
1100
1101
6
    return out;
1102
1103
4
 fail:
1104
4
    lzma_end(&strm);
1105
4
    free(out);
1106
4
    return NULL;
1107
6
}
1108
#endif
1109
1110
/* ----------------------------------------------------------------------
1111
 * CRAM blocks - the dynamically growable data block. We have code to
1112
 * create, update, (un)compress and read/write.
1113
 *
1114
 * These are derived from the deflate_interlaced.c blocks, but with the
1115
 * CRAM extension of content types and IDs.
1116
 */
1117
1118
/*
1119
 * Allocates a new cram_block structure with a specified content_type and
1120
 * id.
1121
 *
1122
 * Returns block pointer on success
1123
 *         NULL on failure
1124
 */
1125
cram_block *cram_new_block(enum cram_content_type content_type,
1126
849k
                           int content_id) {
1127
849k
    cram_block *b = malloc(sizeof(*b));
1128
849k
    if (!b)
1129
0
        return NULL;
1130
849k
    b->method = b->orig_method = RAW;
1131
849k
    b->content_type = content_type;
1132
849k
    b->content_id = content_id;
1133
849k
    b->comp_size = 0;
1134
849k
    b->uncomp_size = 0;
1135
849k
    b->data = NULL;
1136
849k
    b->alloc = 0;
1137
849k
    b->byte = 0;
1138
849k
    b->bit = 7; // MSB
1139
849k
    b->crc32 = 0;
1140
849k
    b->idx = 0;
1141
849k
    b->m = NULL;
1142
1143
849k
    return b;
1144
849k
}
1145
1146
/*
1147
 * Reads a block from a cram file.
1148
 * Returns cram_block pointer on success.
1149
 *         NULL on failure
1150
 */
1151
10.5k
cram_block *cram_read_block(cram_fd *fd) {
1152
10.5k
    cram_block *b = malloc(sizeof(*b));
1153
10.5k
    unsigned char c;
1154
10.5k
    uint32_t crc = 0;
1155
10.5k
    if (!b)
1156
0
        return NULL;
1157
1158
    //fprintf(stderr, "Block at %d\n", (int)ftell(fd->fp));
1159
1160
10.5k
    if (-1 == (b->method      = hgetc(fd->fp))) { free(b); return NULL; }
1161
10.5k
    if (b->method > TOK3) {
1162
128
        hts_log_error("Unknown block compression method %d", (int) b->method);
1163
128
        free(b); return NULL;
1164
128
    }
1165
10.4k
    c = b->method; crc = crc32(crc, &c, 1);
1166
10.4k
    if (-1 == (b->content_type= hgetc(fd->fp))) { free(b); return NULL; }
1167
10.3k
    c = b->content_type; crc = crc32(crc, &c, 1);
1168
10.3k
    if (-1 == fd->vv.varint_decode32_crc(fd, &b->content_id, &crc))  { free(b); return NULL; }
1169
10.3k
    if (-1 == fd->vv.varint_decode32_crc(fd, &b->comp_size, &crc))   { free(b); return NULL; }
1170
10.3k
    if (-1 == fd->vv.varint_decode32_crc(fd, &b->uncomp_size, &crc)) { free(b); return NULL; }
1171
1172
    //fprintf(stderr, "  method %d, ctype %d, cid %d, csize %d, ucsize %d\n",
1173
    //      b->method, b->content_type, b->content_id, b->comp_size, b->uncomp_size);
1174
1175
10.3k
    if (b->method == RAW) {
1176
3.61k
        if (b->uncomp_size < 0 || b->comp_size != b->uncomp_size) {
1177
124
            free(b);
1178
124
            return NULL;
1179
124
        }
1180
3.49k
        b->alloc = b->uncomp_size;
1181
3.49k
        if (!(b->data = malloc(b->uncomp_size))){ free(b); return NULL; }
1182
3.49k
        if (b->uncomp_size != hread(fd->fp, b->data, b->uncomp_size)) {
1183
15
            free(b->data);
1184
15
            free(b);
1185
15
            return NULL;
1186
15
        }
1187
6.70k
    } else {
1188
6.70k
        if (b->comp_size < 0 || b->uncomp_size < 0) {
1189
34
            free(b);
1190
34
            return NULL;
1191
34
        }
1192
6.67k
        b->alloc = b->comp_size;
1193
6.67k
        if (!(b->data = malloc(b->comp_size)))  { free(b); return NULL; }
1194
6.67k
        if (b->comp_size != hread(fd->fp, b->data, b->comp_size)) {
1195
38
            free(b->data);
1196
38
            free(b);
1197
38
            return NULL;
1198
38
        }
1199
6.67k
    }
1200
1201
10.1k
    if (CRAM_MAJOR_VERS(fd->version) >= 3) {
1202
613
        if (-1 == int32_decode(fd, (int32_t *)&b->crc32)) {
1203
5
            free(b->data);
1204
5
            free(b);
1205
5
            return NULL;
1206
5
        }
1207
1208
608
        b->crc32_checked = fd->ignore_md5;
1209
608
        b->crc_part = crc;
1210
9.50k
    } else {
1211
9.50k
        b->crc32_checked = 1; // CRC not present
1212
9.50k
    }
1213
1214
10.1k
    b->orig_method = b->method;
1215
10.1k
    b->idx = 0;
1216
10.1k
    b->byte = 0;
1217
10.1k
    b->bit = 7; // MSB
1218
1219
10.1k
    return b;
1220
10.1k
}
1221
1222
1223
/*
1224
 * Computes the size of a cram block, including the block
1225
 * header itself.
1226
 */
1227
0
uint32_t cram_block_size(cram_block *b) {
1228
0
    unsigned char dat[100], *cp = dat;;
1229
0
    uint32_t sz;
1230
1231
0
    *cp++ = b->method;
1232
0
    *cp++ = b->content_type;
1233
0
    cp += itf8_put((char*)cp, b->content_id);
1234
0
    cp += itf8_put((char*)cp, b->comp_size);
1235
0
    cp += itf8_put((char*)cp, b->uncomp_size);
1236
1237
0
    sz = cp-dat + 4;
1238
0
    sz += b->method == RAW ? b->uncomp_size : b->comp_size;
1239
1240
0
    return sz;
1241
0
}
1242
1243
/*
1244
 * Writes a CRAM block.
1245
 * Returns 0 on success
1246
 *        -1 on failure
1247
 */
1248
302k
int cram_write_block(cram_fd *fd, cram_block *b) {
1249
302k
    char vardata[100];
1250
302k
    int vardata_o = 0;
1251
1252
302k
    assert(b->method != RAW || (b->comp_size == b->uncomp_size));
1253
1254
302k
    if (hputc(b->method,       fd->fp)  == EOF) return -1;
1255
302k
    if (hputc(b->content_type, fd->fp)  == EOF) return -1;
1256
302k
    vardata_o += fd->vv.varint_put32(vardata          , vardata+100, b->content_id);
1257
302k
    vardata_o += fd->vv.varint_put32(vardata+vardata_o, vardata+100, b->comp_size);
1258
302k
    vardata_o += fd->vv.varint_put32(vardata+vardata_o, vardata+100, b->uncomp_size);
1259
302k
    if (vardata_o != hwrite(fd->fp, vardata, vardata_o))
1260
0
        return -1;
1261
1262
302k
    if (b->data) {
1263
269k
        if (b->method == RAW) {
1264
217k
            if (b->uncomp_size != hwrite(fd->fp, b->data, b->uncomp_size))
1265
0
                return -1;
1266
217k
        } else {
1267
51.5k
            if (b->comp_size != hwrite(fd->fp, b->data, b->comp_size))
1268
0
                return -1;
1269
51.5k
        }
1270
269k
    } else {
1271
        // Absent blocks should be size 0
1272
33.7k
        assert(b->method == RAW && b->uncomp_size == 0);
1273
33.7k
    }
1274
1275
302k
    if (CRAM_MAJOR_VERS(fd->version) >= 3) {
1276
302k
        char dat[100], *cp = (char *)dat;
1277
302k
        uint32_t crc;
1278
1279
302k
        *cp++ = b->method;
1280
302k
        *cp++ = b->content_type;
1281
302k
        cp += fd->vv.varint_put32(cp, dat+100, b->content_id);
1282
302k
        cp += fd->vv.varint_put32(cp, dat+100, b->comp_size);
1283
302k
        cp += fd->vv.varint_put32(cp, dat+100, b->uncomp_size);
1284
302k
        crc = crc32(0L, (uc *)dat, cp-dat);
1285
1286
302k
        if (b->method == RAW) {
1287
251k
            b->crc32 = crc32(crc, b->data ? b->data : (uc*)"", b->uncomp_size);
1288
251k
        } else {
1289
51.5k
            b->crc32 = crc32(crc, b->data ? b->data : (uc*)"", b->comp_size);
1290
51.5k
        }
1291
1292
302k
        if (-1 == int32_encode(fd, b->crc32))
1293
0
            return -1;
1294
302k
    }
1295
1296
302k
    return 0;
1297
302k
}
1298
1299
/*
1300
 * Frees a CRAM block, deallocating internal data too.
1301
 */
1302
1.07M
void cram_free_block(cram_block *b) {
1303
1.07M
    if (!b)
1304
212k
        return;
1305
859k
    if (b->data)
1306
529k
        free(b->data);
1307
859k
    free(b);
1308
859k
}
1309
1310
/*
1311
 * Uncompresses a CRAM block, if compressed.
1312
 */
1313
7.65k
int cram_uncompress_block(cram_block *b) {
1314
7.65k
    char *uncomp;
1315
7.65k
    size_t uncomp_size = 0;
1316
1317
7.65k
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
1318
    // Pretend the CRC was OK so the fuzzer doesn't have to get it right
1319
7.65k
    b->crc32_checked = 1;
1320
7.65k
#endif
1321
1322
7.65k
    if (b->crc32_checked == 0) {
1323
0
        uint32_t crc = crc32(b->crc_part, b->data ? b->data : (uc *)"", b->alloc);
1324
0
        b->crc32_checked = 1;
1325
0
        if (crc != b->crc32) {
1326
0
            hts_log_error("Block CRC32 failure");
1327
0
            return -1;
1328
0
        }
1329
0
    }
1330
1331
7.65k
    if (b->uncomp_size == 0) {
1332
        // blank block
1333
790
        b->method = RAW;
1334
790
        return 0;
1335
790
    }
1336
7.65k
    assert(b->uncomp_size >= 0); // cram_read_block should ensure this
1337
1338
6.86k
    switch (b->method) {
1339
370
    case RAW:
1340
370
        return 0;
1341
1342
23
    case GZIP:
1343
23
        if (b->uncomp_size / 2048 > b->comp_size) {
1344
            // The maximum compression ratio of gzip is 1032
1345
            // (LZ match of 258 bytes encoded in a 2bit huffman code)
1346
            // so catch blocks that claim to be wildly over this.
1347
7
            hts_log_error("GZIP cram block has impossibly large compression ratio");
1348
7
            return -1;
1349
7
        }
1350
16
        uncomp_size = b->uncomp_size;
1351
16
        uncomp = zlib_mem_inflate((char *)b->data, b->comp_size, &uncomp_size);
1352
1353
16
        if (!uncomp)
1354
16
            return -1;
1355
0
        if (uncomp_size != b->uncomp_size) {
1356
0
            free(uncomp);
1357
0
            return -1;
1358
0
        }
1359
0
        free(b->data);
1360
0
        b->data = (unsigned char *)uncomp;
1361
0
        b->alloc = uncomp_size;
1362
0
        b->method = RAW;
1363
0
        break;
1364
1365
0
#ifdef HAVE_LIBBZ2
1366
4
    case BZIP2: {
1367
4
        unsigned int usize = b->uncomp_size;
1368
4
        if (!(uncomp = malloc(usize)))
1369
0
            return -1;
1370
4
        if (BZ_OK != BZ2_bzBuffToBuffDecompress(uncomp, &usize,
1371
4
                                                (char *)b->data, b->comp_size,
1372
4
                                                0, 0)) {
1373
4
            free(uncomp);
1374
4
            return -1;
1375
4
        }
1376
0
        free(b->data);
1377
0
        b->data = (unsigned char *)uncomp;
1378
0
        b->alloc = usize;
1379
0
        b->method = RAW;
1380
0
        b->uncomp_size = usize; // Just in case it differs
1381
0
        break;
1382
4
    }
1383
#else
1384
    case BZIP2:
1385
        hts_log_error("Bzip2 compression is not compiled into this version. Please rebuild and try again");
1386
        return -1;
1387
#endif
1388
1389
0
#ifdef HAVE_LIBLZMA
1390
10
    case LZMA:
1391
10
        uncomp = lzma_mem_inflate((char *)b->data, b->comp_size, &uncomp_size);
1392
10
        if (!uncomp)
1393
4
            return -1;
1394
6
        if (uncomp_size != b->uncomp_size) {
1395
6
            free(uncomp);
1396
6
            return -1;
1397
6
        }
1398
0
        free(b->data);
1399
0
        b->data = (unsigned char *)uncomp;
1400
0
        b->alloc = uncomp_size;
1401
0
        b->method = RAW;
1402
0
        break;
1403
#else
1404
    case LZMA:
1405
        hts_log_error("Lzma compression is not compiled into this version. Please rebuild and try again");
1406
        return -1;
1407
        break;
1408
#endif
1409
1410
554
    case RANS: {
1411
554
        unsigned int usize = b->uncomp_size, usize2 = 0;
1412
554
        uncomp = (char *)rans_uncompress(b->data, b->comp_size, &usize2);
1413
554
        if (!uncomp)
1414
277
            return -1;
1415
277
        if (usize != usize2) {
1416
260
            free(uncomp);
1417
260
            return -1;
1418
260
        }
1419
17
        free(b->data);
1420
17
        b->data = (unsigned char *)uncomp;
1421
17
        b->alloc = usize2;
1422
17
        b->method = RAW;
1423
17
        b->uncomp_size = usize2; // Just in case it differs
1424
        //fprintf(stderr, "Expanded %d to %d\n", b->comp_size, b->uncomp_size);
1425
17
        break;
1426
277
    }
1427
1428
1.04k
    case FQZ: {
1429
1.04k
        uncomp_size = b->uncomp_size;
1430
1.04k
        uncomp = fqz_decompress((char *)b->data, b->comp_size, &uncomp_size, NULL, 0);
1431
1.04k
        if (!uncomp)
1432
807
            return -1;
1433
233
        free(b->data);
1434
233
        b->data = (unsigned char *)uncomp;
1435
233
        b->alloc = uncomp_size;
1436
233
        b->method = RAW;
1437
233
        b->uncomp_size = uncomp_size;
1438
233
        break;
1439
1.04k
    }
1440
1441
1.42k
    case RANS_PR0: {
1442
1.42k
        unsigned int usize = b->uncomp_size, usize2 = 0;
1443
1.42k
        uncomp = (char *)rans_uncompress_4x16(b->data, b->comp_size, &usize2);
1444
1.42k
        if (!uncomp)
1445
832
            return -1;
1446
593
        if (usize != usize2) {
1447
236
            free(uncomp);
1448
236
            return -1;
1449
236
        }
1450
357
        b->orig_method = RANSPR;
1451
357
        free(b->data);
1452
357
        b->data = (unsigned char *)uncomp;
1453
357
        b->alloc = usize2;
1454
357
        b->method = RAW;
1455
357
        b->uncomp_size = usize2; // Just in case it differs
1456
        //fprintf(stderr, "Expanded %d to %d\n", b->comp_size, b->uncomp_size);
1457
357
        break;
1458
593
    }
1459
1460
658
    case ARITH_PR0: {
1461
658
        unsigned int usize = b->uncomp_size, usize2 = 0;
1462
658
        uncomp = (char *)arith_uncompress_to(b->data, b->comp_size, NULL, &usize2);
1463
658
        if (!uncomp)
1464
452
            return -1;
1465
206
        if (usize != usize2) {
1466
77
            free(uncomp);
1467
77
            return -1;
1468
77
        }
1469
129
        b->orig_method = ARITH;
1470
129
        free(b->data);
1471
129
        b->data = (unsigned char *)uncomp;
1472
129
        b->alloc = usize2;
1473
129
        b->method = RAW;
1474
129
        b->uncomp_size = usize2; // Just in case it differs
1475
        //fprintf(stderr, "Expanded %d to %d\n", b->comp_size, b->uncomp_size);
1476
129
        break;
1477
206
    }
1478
1479
2.77k
    case TOK3: {
1480
2.77k
        uint32_t out_len;
1481
2.77k
        uint8_t *cp = tok3_decode_names(b->data, b->comp_size, &out_len);
1482
2.77k
        if (!cp)
1483
2.63k
            return -1;
1484
143
        b->orig_method = TOK3;
1485
143
        b->method = RAW;
1486
143
        free(b->data);
1487
143
        b->data = cp;
1488
143
        b->alloc = out_len;
1489
143
        b->uncomp_size = out_len;
1490
143
        break;
1491
2.77k
    }
1492
1493
0
    default:
1494
0
        return -1;
1495
6.86k
    }
1496
1497
879
    return 0;
1498
6.86k
}
1499
1500
static char *cram_compress_by_method(cram_slice *s, char *in, size_t in_size,
1501
                                     int content_id, size_t *out_size,
1502
                                     enum cram_block_method_int method,
1503
767k
                                     int level, int strat) {
1504
767k
    switch (method) {
1505
95.7k
    case GZIP:
1506
158k
    case GZIP_RLE:
1507
295k
    case GZIP_1:
1508
        // Read names bizarrely benefit from zlib over libdeflate for
1509
        // mid-range compression levels.  Focusing purely of ratio or
1510
        // speed, libdeflate still wins.  It also seems to win for
1511
        // other data series too.
1512
        //
1513
        // Eg RN at level 5;  libdeflate=55.9MB  zlib=51.6MB
1514
#ifdef HAVE_LIBDEFLATE
1515
#  if (LIBDEFLATE_VERSION_MAJOR < 1 || (LIBDEFLATE_VERSION_MAJOR == 1 && LIBDEFLATE_VERSION_MINOR <= 8))
1516
        if (content_id == DS_RN && level >= 4 && level <= 7)
1517
            return zlib_mem_deflate(in, in_size, out_size, level, strat);
1518
        else
1519
#  endif
1520
            return libdeflate_deflate(in, in_size, out_size, level, strat);
1521
#else
1522
295k
        return zlib_mem_deflate(in, in_size, out_size, level, strat);
1523
0
#endif
1524
1525
0
    case BZIP2: {
1526
0
#ifdef HAVE_LIBBZ2
1527
0
        unsigned int comp_size = in_size*1.01 + 600;
1528
0
        char *comp = malloc(comp_size);
1529
0
        if (!comp)
1530
0
            return NULL;
1531
1532
0
        if (BZ_OK != BZ2_bzBuffToBuffCompress(comp, &comp_size,
1533
0
                                              in, in_size,
1534
0
                                              level, 0, 30)) {
1535
0
            free(comp);
1536
0
            return NULL;
1537
0
        }
1538
0
        *out_size = comp_size;
1539
0
        return comp;
1540
#else
1541
        return NULL;
1542
#endif
1543
0
    }
1544
1545
0
    case FQZ:
1546
0
    case FQZ_b:
1547
0
    case FQZ_c:
1548
0
    case FQZ_d: {
1549
        // Extract the necessary portion of the slice into an fqz_slice struct.
1550
        // These previously were the same thing, but this permits us to detach
1551
        // the codec from the rest of this CRAM implementation.
1552
0
        fqz_slice *f = malloc(2*s->hdr->num_records * sizeof(uint32_t) + sizeof(fqz_slice));
1553
0
        if (!f)
1554
0
            return NULL;
1555
0
        f->num_records = s->hdr->num_records;
1556
0
        f->len = (uint32_t *)(((char *)f) + sizeof(fqz_slice));
1557
0
        f->flags = f->len + s->hdr->num_records;
1558
0
        int i;
1559
0
        for (i = 0; i < s->hdr->num_records; i++) {
1560
0
            f->flags[i] = s->crecs[i].flags;
1561
0
            f->len[i] = (i+1 < s->hdr->num_records
1562
0
                         ? s->crecs[i+1].qual - s->crecs[i].qual
1563
0
                         : s->block[DS_QS]->uncomp_size - s->crecs[i].qual);
1564
0
        }
1565
0
        char *comp = fqz_compress(strat & 0xff /* cram vers */, f,
1566
0
                                  in, in_size, out_size, strat >> 8, NULL);
1567
0
        free(f);
1568
0
        return comp;
1569
0
    }
1570
1571
0
    case LZMA:
1572
0
#ifdef HAVE_LIBLZMA
1573
0
        return lzma_mem_deflate(in, in_size, out_size, level);
1574
#else
1575
        return NULL;
1576
#endif
1577
1578
0
    case RANS0:
1579
0
    case RANS1: {
1580
0
        unsigned int out_size_i;
1581
0
        unsigned char *cp;
1582
0
        cp = rans_compress((unsigned char *)in, in_size, &out_size_i,
1583
0
                           method == RANS0 ? 0 : 1);
1584
0
        *out_size = out_size_i;
1585
0
        return (char *)cp;
1586
0
    }
1587
1588
109k
    case RANS_PR0:
1589
172k
    case RANS_PR1:
1590
255k
    case RANS_PR64:
1591
318k
    case RANS_PR9:
1592
387k
    case RANS_PR128:
1593
387k
    case RANS_PR129:
1594
387k
    case RANS_PR192:
1595
450k
    case RANS_PR193: {
1596
450k
        unsigned int out_size_i;
1597
450k
        unsigned char *cp;
1598
1599
        // see enum cram_block. We map RANS_* methods to order bit-fields
1600
450k
        static int methmap[] = { 1, 64,9, 128,129, 192,193 };
1601
1602
450k
        int m = method == RANS_PR0 ? 0 : methmap[method - RANS_PR1];
1603
450k
        cp = rans_compress_4x16((unsigned char *)in, in_size, &out_size_i,
1604
450k
                                m | RANS_ORDER_SIMD_AUTO);
1605
450k
        *out_size = out_size_i;
1606
450k
        return (char *)cp;
1607
387k
    }
1608
1609
0
    case ARITH_PR0:
1610
0
    case ARITH_PR1:
1611
0
    case ARITH_PR64:
1612
0
    case ARITH_PR9:
1613
0
    case ARITH_PR128:
1614
0
    case ARITH_PR129:
1615
0
    case ARITH_PR192:
1616
0
    case ARITH_PR193: {
1617
0
        unsigned int out_size_i;
1618
0
        unsigned char *cp;
1619
1620
        // see enum cram_block. We map ARITH_* methods to order bit-fields
1621
0
        static int methmap[] = { 1, 64,9, 128,129, 192,193 };
1622
1623
0
        cp = arith_compress_to((unsigned char *)in, in_size, NULL, &out_size_i,
1624
0
                               method == ARITH_PR0 ? 0 : methmap[method - ARITH_PR1]);
1625
0
        *out_size = out_size_i;
1626
0
        return (char *)cp;
1627
0
    }
1628
1629
20.9k
    case TOK3:
1630
20.9k
    case TOKA: {
1631
20.9k
        int out_len;
1632
20.9k
        int lev = level;
1633
20.9k
        if (method == TOK3 && lev > 3)
1634
20.9k
            lev = 3;
1635
20.9k
        uint8_t *cp = tok3_encode_names(in, in_size, lev, strat, &out_len, NULL);
1636
20.9k
        *out_size = out_len;
1637
20.9k
        return (char *)cp;
1638
20.9k
    }
1639
1640
0
    case RAW:
1641
0
        break;
1642
1643
0
    default:
1644
0
        return NULL;
1645
767k
    }
1646
1647
0
    return NULL;
1648
767k
}
1649
1650
/*
1651
 * A copy of cram_compress_block2 with added recursion detection.
1652
 * This is only called for error handling where the auto-tuning has failed.
1653
 * The simplest way of doing this is recursion + an additional argument, but
1654
 * we didn't want to complicate the existing code hence this is static.
1655
 */
1656
static int cram_compress_block3(cram_fd *fd, cram_slice *s,
1657
                                cram_block *b, cram_metrics *metrics,
1658
                                int method, int level,
1659
511k
                                int recurse) {
1660
1661
511k
    if (!b)
1662
32.3k
        return 0;
1663
1664
478k
    int orig_method = method;
1665
478k
    char *comp = NULL;
1666
478k
    size_t comp_size = 0;
1667
478k
    int strat;
1668
1669
    // Internally we have parameterised methods that externally map
1670
    // to the same CRAM method value.
1671
    // See enum_cram_block_method_int in cram_structs.h.
1672
478k
    int methmap[] = {
1673
        // Externally defined values
1674
478k
        RAW, GZIP, BZIP2, LZMA, RANS, RANSPR, ARITH, FQZ, TOK3,
1675
1676
        // Reserved for possible expansion
1677
478k
        0, 0,
1678
1679
        // Internally parameterised versions matching back to above
1680
        // external values
1681
478k
        GZIP, GZIP,
1682
478k
        FQZ, FQZ, FQZ,
1683
478k
        RANS,
1684
478k
        RANSPR, RANSPR, RANSPR, RANSPR, RANSPR, RANSPR, RANSPR,
1685
478k
        TOK3,
1686
478k
        ARITH,  ARITH,  ARITH,  ARITH,  ARITH,  ARITH,  ARITH,
1687
478k
    };
1688
1689
478k
    if (b->method != RAW) {
1690
        // Maybe already compressed if s->block[0] was compressed and
1691
        // we have e.g. s->block[DS_BA] set to s->block[0] due to only
1692
        // one base type present and hence using E_HUFFMAN on block 0.
1693
        // A second explicit attempt to compress the same block then
1694
        // occurs.
1695
0
        return 0;
1696
0
    }
1697
1698
478k
    if (method == -1) {
1699
10.2k
        method = 1<<GZIP;
1700
10.2k
        if (fd->use_bz2)
1701
0
            method |= 1<<BZIP2;
1702
10.2k
        if (fd->use_lzma)
1703
0
            method |= 1<<LZMA;
1704
10.2k
    }
1705
1706
478k
    if (level == -1)
1707
10.2k
        level = fd->level;
1708
1709
    //fprintf(stderr, "IN: block %d, sz %d\n", b->content_id, b->uncomp_size);
1710
1711
478k
    if (method == RAW || level == 0 || b->uncomp_size == 0) {
1712
258k
        b->method = RAW;
1713
258k
        b->comp_size = b->uncomp_size;
1714
        //fprintf(stderr, "Skip block id %d\n", b->content_id);
1715
258k
        return 0;
1716
258k
    }
1717
1718
220k
#ifndef ABS
1719
220k
#    define ABS(a) ((a)>=0?(a):-(a))
1720
220k
#endif
1721
1722
220k
    if (metrics) {
1723
209k
        pthread_mutex_lock(&fd->metrics_lock);
1724
        // Sudden changes in size trigger a retrial.  These are mainly
1725
        // triggered when switching to sorted / unsorted, where the number
1726
        // of elements in a slice radically changes.
1727
        //
1728
        // We also get large fluctuations based on genome coordinate for
1729
        // e.g. SA:Z and SC series, but we consider the typical scale of
1730
        // delta between blocks and use this to look for abnormality.
1731
1732
        // Equivalent to (but minus possible integer overflow)
1733
        //   (b->uncomp_size + 1000)/4 > metrics->input_avg_sz+1000 ||
1734
        //    b->uncomp_size + 1000    < (metrics->input_avg_sz+1000)/4)
1735
209k
        if (metrics->input_avg_sz &&
1736
54.6k
            (b->uncomp_size/4 - 750 > metrics->input_avg_sz ||
1737
53.6k
             b->uncomp_size         < metrics->input_avg_sz/4 - 750) &&
1738
1.22k
            ABS(b->uncomp_size-metrics->input_avg_sz)/10
1739
1.22k
                > metrics->input_avg_delta) {
1740
154
            metrics->next_trial = 0;
1741
154
        }
1742
1743
209k
        if (metrics->trial > 0 || --metrics->next_trial <= 0) {
1744
83.8k
            int m, unpackable = metrics->unpackable;
1745
83.8k
            size_t sz_best = b->uncomp_size;
1746
83.8k
            size_t sz[CRAM_MAX_METHOD] = {0};
1747
83.8k
            int method_best = 0; // RAW
1748
83.8k
            char *c_best = NULL, *c = NULL;
1749
1750
83.8k
            metrics->input_avg_delta =
1751
83.8k
                0.9 * (metrics->input_avg_delta +
1752
83.8k
                       ABS(b->uncomp_size - metrics->input_avg_sz));
1753
1754
83.8k
            metrics->input_avg_sz += b->uncomp_size*.2;
1755
83.8k
            metrics->input_avg_sz *= 0.8;
1756
1757
83.8k
            if (metrics->revised_method)
1758
31.8k
                method = metrics->revised_method;
1759
51.9k
            else
1760
51.9k
                metrics->revised_method = method;
1761
1762
83.8k
            if (metrics->next_trial <= 0) {
1763
1.31k
                metrics->next_trial = TRIAL_SPAN;
1764
1.31k
                metrics->trial = NTRIALS;
1765
43.2k
                for (m = 0; m < CRAM_MAX_METHOD; m++)
1766
41.9k
                    metrics->sz[m] /= 2;
1767
1.31k
                metrics->unpackable = 0;
1768
1.31k
            }
1769
1770
            // Compress this block using the best method
1771
83.8k
            if (unpackable && CRAM_MAJOR_VERS(fd->version) > 3) {
1772
                // No point trying bit-pack if 17+ symbols.
1773
0
                if (method & (1<<RANS_PR128))
1774
0
                    method = (method|(1<<RANS_PR0))&~(1<<RANS_PR128);
1775
0
                if (method & (1<<RANS_PR129))
1776
0
                    method = (method|(1<<RANS_PR1))&~(1<<RANS_PR129);
1777
0
                if (method & (1<<RANS_PR192))
1778
0
                    method = (method|(1<<RANS_PR64))&~(1<<RANS_PR192);
1779
0
                if (method & (1<<RANS_PR193))
1780
0
                    method = (method|(1<<RANS_PR64)|(1<<RANS_PR1))&~(1<<RANS_PR193);
1781
1782
0
                if (method & (1<<ARITH_PR128))
1783
0
                    method = (method|(1<<ARITH_PR0))&~(1<<ARITH_PR128);
1784
0
                if (method & (1<<ARITH_PR129))
1785
0
                    method = (method|(1<<ARITH_PR1))&~(1<<ARITH_PR129);
1786
0
                if (method & (1<<ARITH_PR192))
1787
0
                    method = (method|(1<<ARITH_PR64))&~(1<<ARITH_PR192);
1788
0
                if (method & (1u<<ARITH_PR193))
1789
0
                    method = (method|(1<<ARITH_PR64)|(1<<ARITH_PR1))&~(1u<<ARITH_PR193);
1790
0
            }
1791
1792
            // Libdeflate doesn't have a Z_RLE strategy.
1793
            // We treat it as level 1, but iff we haven't also
1794
            // explicitly listed that in the method list.
1795
#ifdef HAVE_LIBDEFLATE
1796
            if ((method & (1<<GZIP_RLE)) && (method & (1<<GZIP_1)))
1797
                method &= ~(1<<GZIP_RLE);
1798
#endif
1799
1800
83.8k
            pthread_mutex_unlock(&fd->metrics_lock);
1801
1802
2.76M
            for (m = 0; m < CRAM_MAX_METHOD; m++) {
1803
2.68M
                if (method & (1u<<m)) {
1804
630k
                    int lvl = level;
1805
630k
                    switch (m) {
1806
83.8k
                    case GZIP:     strat = Z_FILTERED; break;
1807
83.8k
                    case GZIP_1:   strat = Z_DEFAULT_STRATEGY; lvl = 1; break;
1808
63.1k
                    case GZIP_RLE: strat = Z_RLE; break;
1809
0
                    case FQZ:      strat = CRAM_MAJOR_VERS(fd->version); break;
1810
0
                    case FQZ_b:    strat = CRAM_MAJOR_VERS(fd->version)+256; break;
1811
0
                    case FQZ_c:    strat = CRAM_MAJOR_VERS(fd->version)+2*256; break;
1812
0
                    case FQZ_d:    strat = CRAM_MAJOR_VERS(fd->version)+3*256; break;
1813
20.6k
                    case TOK3:     strat = 0; break;
1814
0
                    case TOKA:     strat = 1; break;
1815
379k
                    default:       strat = 0;
1816
630k
                    }
1817
1818
630k
                    c = cram_compress_by_method(s, (char *)b->data, b->uncomp_size,
1819
630k
                                                b->content_id, &sz[m], m, lvl, strat);
1820
1821
630k
                    if (c && sz_best > sz[m]) {
1822
46.0k
                        sz_best = sz[m];
1823
46.0k
                        method_best = m;
1824
46.0k
                        if (c_best)
1825
21.0k
                            free(c_best);
1826
46.0k
                        c_best = c;
1827
584k
                    } else if (c) {
1828
582k
                        free(c);
1829
582k
                    } else {
1830
2.27k
                        sz[m] = UINT_MAX; // arbitrarily worse than raw
1831
2.27k
                    }
1832
2.05M
                } else {
1833
2.05M
                    sz[m] = UINT_MAX; // arbitrarily worse than raw
1834
2.05M
                }
1835
2.68M
            }
1836
1837
83.8k
            if (c_best) {
1838
24.9k
                free(b->data);
1839
24.9k
                b->data = (unsigned char *)c_best;
1840
24.9k
                b->method = method_best; // adjusted to methmap[method_best] later
1841
24.9k
                b->comp_size = sz_best;
1842
24.9k
            }
1843
1844
            // Accumulate stats for all methods tried
1845
83.8k
            pthread_mutex_lock(&fd->metrics_lock);
1846
2.76M
            for (m = 0; m < CRAM_MAX_METHOD; m++)
1847
                // don't be overly sure on small blocks.
1848
                // +2000 means eg bzip2 vs gzip (1.07 to 1.04) or gz vs rans1
1849
                // needs to be at least 60 bytes smaller to overcome the
1850
                // fixed size addition.
1851
2.68M
                metrics->sz[m] += sz[m]+2000;
1852
1853
            // When enough trials performed, find the best on average
1854
83.8k
            if (--metrics->trial == 0) {
1855
18.2k
                int best_method = RAW;
1856
18.2k
                int best_sz = INT_MAX;
1857
1858
                // Relative costs of methods. See enum_cram_block_method_int
1859
                // and methmap
1860
18.2k
                double meth_cost[32] = {
1861
                    // Externally defined methods
1862
18.2k
                    1,    // 0  raw
1863
18.2k
                    1.04, // 1  gzip (Z_FILTERED)
1864
18.2k
                    1.07, // 2  bzip2
1865
18.2k
                    1.08, // 3  lzma
1866
18.2k
                    1.00, // 4  rans    (O0)
1867
18.2k
                    1.00, // 5  ranspr  (O0)
1868
18.2k
                    1.04, // 6  arithpr (O0)
1869
18.2k
                    1.05, // 7  fqz
1870
18.2k
                    1.05, // 8  tok3 (rans)
1871
18.2k
                    1.00, 1.00, // 9,10 reserved
1872
1873
                    // Parameterised versions of above
1874
18.2k
                    1.01, // gzip rle
1875
18.2k
                    1.01, // gzip -1
1876
1877
18.2k
                    1.05, 1.05, 1.05, // FQZ_b,c,d
1878
1879
18.2k
                    1.01, // rans O1
1880
1881
18.2k
                    1.01, // rans_pr1
1882
18.2k
                    1.00, // rans_pr64; if smaller, usually fast
1883
18.2k
                    1.03, // rans_pr65/9
1884
18.2k
                    1.00, // rans_pr128
1885
18.2k
                    1.01, // rans_pr129
1886
18.2k
                    1.00, // rans_pr192
1887
18.2k
                    1.01, // rans_pr193
1888
1889
18.2k
                    1.07, // tok3 arith
1890
1891
18.2k
                    1.04, // arith_pr1
1892
18.2k
                    1.04, // arith_pr64
1893
18.2k
                    1.04, // arith_pr9
1894
18.2k
                    1.03, // arith_pr128
1895
18.2k
                    1.04, // arith_pr129
1896
18.2k
                    1.04, // arith_pr192
1897
18.2k
                    1.04, // arith_pr193
1898
18.2k
                };
1899
1900
                // Scale methods by cost based on compression level
1901
18.2k
                if (fd->level <= 1) {
1902
0
                    for (m = 0; m < CRAM_MAX_METHOD; m++)
1903
0
                        metrics->sz[m] *= 1+(meth_cost[m]-1)*4;
1904
18.2k
                } else if (fd->level <= 3) {
1905
0
                    for (m = 0; m < CRAM_MAX_METHOD; m++)
1906
0
                        metrics->sz[m] *= 1+(meth_cost[m]-1);
1907
18.2k
                } else if (fd->level <= 6) {
1908
601k
                    for (m = 0; m < CRAM_MAX_METHOD; m++)
1909
583k
                        metrics->sz[m] *= 1+(meth_cost[m]-1)/2;
1910
18.2k
                } else if (fd->level <= 7) {
1911
0
                    for (m = 0; m < CRAM_MAX_METHOD; m++)
1912
0
                        metrics->sz[m] *= 1+(meth_cost[m]-1)/3;
1913
0
                } // else cost is ignored
1914
1915
                // Ensure these are never used; BSC and ZSTD
1916
18.2k
                metrics->sz[9] = metrics->sz[10] = INT_MAX;
1917
1918
601k
                for (m = 0; m < CRAM_MAX_METHOD; m++) {
1919
583k
                    if ((!metrics->sz[m]) || (!(method & (1u<<m))))
1920
465k
                        continue;
1921
1922
118k
                    if (best_sz > metrics->sz[m])
1923
42.7k
                        best_sz = metrics->sz[m], best_method = m;
1924
118k
                }
1925
1926
18.2k
                if (best_method != metrics->method) {
1927
                    //metrics->trial = (NTRIALS+1)/2; // be sure
1928
                    //metrics->next_trial /= 1.5;
1929
10.7k
                    metrics->consistency = 0;
1930
10.7k
                } else {
1931
7.44k
                    metrics->next_trial *= MIN(2, 1+metrics->consistency/4.0);
1932
7.44k
                    metrics->consistency++;
1933
7.44k
                }
1934
1935
18.2k
                metrics->method = best_method;
1936
18.2k
                switch (best_method) {
1937
219
                case GZIP:     strat = Z_FILTERED; break;
1938
7.49k
                case GZIP_1:   strat = Z_DEFAULT_STRATEGY; break;
1939
1
                case GZIP_RLE: strat = Z_RLE; break;
1940
0
                case FQZ:      strat = CRAM_MAJOR_VERS(fd->version); break;
1941
0
                case FQZ_b:    strat = CRAM_MAJOR_VERS(fd->version)+256; break;
1942
0
                case FQZ_c:    strat = CRAM_MAJOR_VERS(fd->version)+2*256; break;
1943
0
                case FQZ_d:    strat = CRAM_MAJOR_VERS(fd->version)+3*256; break;
1944
435
                case TOK3:     strat = 0; break;
1945
0
                case TOKA:     strat = 1; break;
1946
10.0k
                default:       strat = 0;
1947
18.2k
                }
1948
18.2k
                metrics->strat  = strat;
1949
1950
                // If we see at least MAXFAIL trials in a row for a specific
1951
                // compression method with more than MAXDELTA aggregate
1952
                // size then we drop this from the list of methods used
1953
                // for this block type.
1954
145k
#define MAXDELTA 0.20
1955
396k
#define MAXFAILS 4
1956
601k
                for (m = 0; m < CRAM_MAX_METHOD; m++) {
1957
583k
                    if (best_method == m) {
1958
18.2k
                        metrics->cnt[m] = 0;
1959
18.2k
                        metrics->extra[m] = 0;
1960
565k
                    } else if (best_sz < metrics->sz[m]) {
1961
396k
                        double r = (double)metrics->sz[m] / best_sz - 1;
1962
396k
                        int mul = 1+(fd->level>=7);
1963
396k
                        if (++metrics->cnt[m] >= MAXFAILS*mul &&
1964
145k
                            (metrics->extra[m] += r) >= MAXDELTA*mul)
1965
82.6k
                            method &= ~(1u<<m);
1966
1967
                        // Special case for fqzcomp as it rarely changes
1968
396k
                        if (m == FQZ || m == FQZ_b || m == FQZ_c || m == FQZ_d) {
1969
65.8k
                            if (metrics->sz[m] > best_sz)
1970
65.8k
                                method &= ~(1u<<m);
1971
65.8k
                        }
1972
396k
                    }
1973
583k
                }
1974
1975
                //if (fd->verbose > 1 && method != metrics->revised_method)
1976
                //    fprintf(stderr, "%d: revising method from %x to %x\n",
1977
                //          b->content_id, metrics->revised_method, method);
1978
18.2k
                metrics->revised_method = method;
1979
18.2k
            }
1980
83.8k
            pthread_mutex_unlock(&fd->metrics_lock);
1981
125k
        } else {
1982
125k
            metrics->input_avg_delta =
1983
125k
                0.9 * (metrics->input_avg_delta +
1984
125k
                       ABS(b->uncomp_size - metrics->input_avg_sz));
1985
1986
125k
            metrics->input_avg_sz += b->uncomp_size*.2;
1987
125k
            metrics->input_avg_sz *= 0.8;
1988
1989
125k
            strat = metrics->strat;
1990
125k
            method = metrics->method;
1991
1992
125k
            pthread_mutex_unlock(&fd->metrics_lock);
1993
125k
            comp = cram_compress_by_method(s, (char *)b->data, b->uncomp_size,
1994
125k
                                           b->content_id, &comp_size, method,
1995
125k
                                           method == GZIP_1 ? 1 : level,
1996
125k
                                           strat);
1997
125k
            if (!comp) {
1998
                // Our cached best method failed, but maybe another works?
1999
                // Rerun with trial mode engaged again.
2000
280
                if (!recurse) {
2001
280
                    hts_log_warning("Compressed block ID %d method %s failed, "
2002
280
                                    "redoing trial", b->content_id,
2003
280
                                    cram_block_method2str(method));
2004
280
                    pthread_mutex_lock(&fd->metrics_lock);
2005
280
                    metrics->trial = NTRIALS;
2006
280
                    metrics->next_trial = TRIAL_SPAN;
2007
280
                    metrics->revised_method = orig_method;
2008
280
                    pthread_mutex_unlock(&fd->metrics_lock);
2009
280
                    return cram_compress_block3(fd, s, b, metrics, method,
2010
280
                                                level, 1);
2011
280
                }
2012
0
                return -1;
2013
280
            }
2014
2015
125k
            if (comp_size < b->uncomp_size) {
2016
24.9k
                free(b->data);
2017
24.9k
                b->data = (unsigned char *)comp;
2018
24.9k
                b->comp_size = comp_size;
2019
24.9k
                b->method = method;
2020
100k
            } else {
2021
100k
                free(comp);
2022
100k
            }
2023
125k
        }
2024
2025
209k
    } else {
2026
        // no cached metrics, so just do zlib?
2027
11.2k
        comp = cram_compress_by_method(s, (char *)b->data, b->uncomp_size,
2028
11.2k
                                       b->content_id, &comp_size, GZIP, level, Z_FILTERED);
2029
11.2k
        if (!comp) {
2030
0
            hts_log_error("Compression failed!");
2031
0
            return -1;
2032
0
        }
2033
2034
11.2k
        if (comp_size < b->uncomp_size) {
2035
1.68k
            free(b->data);
2036
1.68k
            b->data = (unsigned char *)comp;
2037
1.68k
            b->comp_size = comp_size;
2038
1.68k
            b->method = GZIP;
2039
9.53k
        } else {
2040
9.53k
            free(comp);
2041
9.53k
        }
2042
11.2k
        strat = Z_FILTERED;
2043
11.2k
    }
2044
2045
220k
    hts_log_info("Compressed block ID %d from %d to %d by method %s",
2046
220k
                 b->content_id, b->uncomp_size, b->comp_size,
2047
220k
                 cram_block_method2str(b->method));
2048
2049
220k
    b->method = methmap[b->method];
2050
2051
220k
    return 0;
2052
220k
}
2053
2054
/*
2055
 * Compresses a block using a selection of compression codecs and options.
2056
 * The best is learnt and used for subsequent slices, periodically resampling.
2057
 *
2058
 * Method and level -1 implies defaults, as specified in cram_fd.
2059
 */
2060
int cram_compress_block2(cram_fd *fd, cram_slice *s,
2061
                         cram_block *b, cram_metrics *metrics,
2062
510k
                         int method, int level) {
2063
510k
    return cram_compress_block3(fd, s, b, metrics, method, level, 0);
2064
510k
}
2065
2066
int cram_compress_block(cram_fd *fd, cram_block *b, cram_metrics *metrics,
2067
10.2k
                        int method, int level) {
2068
10.2k
    return cram_compress_block2(fd, NULL, b, metrics, method, level);
2069
10.2k
}
2070
2071
973k
cram_metrics *cram_new_metrics(void) {
2072
973k
    cram_metrics *m = calloc(1, sizeof(*m));
2073
973k
    if (!m)
2074
0
        return NULL;
2075
973k
    m->trial = NTRIALS-1;
2076
973k
    m->next_trial = TRIAL_SPAN/2; // learn quicker at start
2077
973k
    m->method = RAW;
2078
973k
    m->strat = 0;
2079
973k
    m->revised_method = 0;
2080
973k
    m->unpackable = 0;
2081
2082
973k
    return m;
2083
973k
}
2084
2085
220k
char *cram_block_method2str(enum cram_block_method_int m) {
2086
220k
    switch(m) {
2087
168k
    case RAW:         return "RAW";
2088
6.45k
    case GZIP:        return "GZIP";
2089
0
    case BZIP2:       return "BZIP2";
2090
0
    case LZMA:        return "LZMA";
2091
0
    case RANS0:       return "RANS0";
2092
0
    case RANS1:       return "RANS1";
2093
10
    case GZIP_RLE:    return "GZIP_RLE";
2094
6.41k
    case GZIP_1:      return "GZIP_1";
2095
0
    case FQZ:         return "FQZ";
2096
0
    case FQZ_b:       return "FQZ_b";
2097
0
    case FQZ_c:       return "FQZ_c";
2098
0
    case FQZ_d:       return "FQZ_d";
2099
886
    case RANS_PR0:    return "RANS_PR0";
2100
700
    case RANS_PR1:    return "RANS_PR1";
2101
18.2k
    case RANS_PR64:   return "RANS_PR64";
2102
7
    case RANS_PR9:    return "RANS_PR9";
2103
18.5k
    case RANS_PR128:  return "RANS_PR128";
2104
0
    case RANS_PR129:  return "RANS_PR129";
2105
0
    case RANS_PR192:  return "RANS_PR192";
2106
314
    case RANS_PR193:  return "RANS_PR193";
2107
285
    case TOK3:        return "TOK3_R";
2108
0
    case TOKA:        return "TOK3_A";
2109
0
    case ARITH_PR0:   return "ARITH_PR0";
2110
0
    case ARITH_PR1:   return "ARITH_PR1";
2111
0
    case ARITH_PR64:  return "ARITH_PR64";
2112
0
    case ARITH_PR9:   return "ARITH_PR9";
2113
0
    case ARITH_PR128: return "ARITH_PR128";
2114
0
    case ARITH_PR129: return "ARITH_PR129";
2115
0
    case ARITH_PR192: return "ARITH_PR192";
2116
0
    case ARITH_PR193: return "ARITH_PR193";
2117
0
    case BM_ERROR: break;
2118
220k
    }
2119
0
    return "?";
2120
220k
}
2121
2122
6
char *cram_content_type2str(enum cram_content_type t) {
2123
6
    switch (t) {
2124
3
    case FILE_HEADER:         return "FILE_HEADER";
2125
0
    case COMPRESSION_HEADER:  return "COMPRESSION_HEADER";
2126
0
    case MAPPED_SLICE:        return "MAPPED_SLICE";
2127
0
    case UNMAPPED_SLICE:      return "UNMAPPED_SLICE";
2128
0
    case EXTERNAL:            return "EXTERNAL";
2129
0
    case CORE:                return "CORE";
2130
0
    case CT_ERROR:            break;
2131
6
    }
2132
3
    return "?";
2133
6
}
2134
2135
/* ----------------------------------------------------------------------
2136
 * Reference sequence handling
2137
 *
2138
 * These revolve around the refs_t structure, which may potentially be
2139
 * shared between multiple cram_fd.
2140
 *
2141
 * We start with refs_create() to allocate an empty refs_t and then
2142
 * populate it with @SQ line data using refs_from_header(). This is done on
2143
 * cram_open().  Also at start up we can call cram_load_reference() which
2144
 * is used with "scramble -r foo.fa". This replaces the fd->refs with the
2145
 * new one specified. In either case refs2id() is then called which
2146
 * maps ref_entry names to @SQ ids (refs_t->ref_id[]).
2147
 *
2148
 * Later, possibly within a thread, we will want to know the actual ref
2149
 * seq itself, obtained by calling cram_get_ref().  This may use the
2150
 * UR: or M5: fields or the filename specified in the original
2151
 * cram_load_reference() call.
2152
 *
2153
 * Given the potential for multi-threaded reference usage, we have
2154
 * reference counting (sorry for the confusing double use of "ref") to
2155
 * track the number of callers interested in any specific reference.
2156
 */
2157
2158
/*
2159
 * Frees/unmaps a reference sequence and associated file handles.
2160
 */
2161
5.79k
static void ref_entry_free_seq(ref_entry *e) {
2162
5.79k
    if (e->mf)
2163
0
        mfclose(e->mf);
2164
5.79k
    if (e->seq && !e->mf)
2165
0
        free(e->seq);
2166
2167
5.79k
    e->seq = NULL;
2168
5.79k
    e->mf = NULL;
2169
5.79k
}
2170
2171
20.5k
void refs_free(refs_t *r) {
2172
20.5k
    RP("refs_free()\n");
2173
2174
20.5k
    if (!r)
2175
0
        return;
2176
2177
20.5k
    if (--r->count > 0)
2178
0
        return;
2179
2180
20.5k
    if (r->pool)
2181
20.5k
        string_pool_destroy(r->pool);
2182
2183
20.5k
    if (r->h_meta) {
2184
20.5k
        khint_t k;
2185
2186
37.9k
        for (k = kh_begin(r->h_meta); k != kh_end(r->h_meta); k++) {
2187
17.4k
            ref_entry *e;
2188
2189
17.4k
            if (!kh_exist(r->h_meta, k))
2190
11.6k
                continue;
2191
5.79k
            if (!(e = kh_val(r->h_meta, k)))
2192
0
                continue;
2193
5.79k
            ref_entry_free_seq(e);
2194
5.79k
            free(e);
2195
5.79k
        }
2196
2197
20.5k
        kh_destroy(refs, r->h_meta);
2198
20.5k
    }
2199
2200
20.5k
    if (r->ref_id)
2201
10.5k
        free(r->ref_id);
2202
2203
20.5k
    if (r->fp)
2204
0
        bgzf_close(r->fp);
2205
2206
20.5k
    pthread_mutex_destroy(&r->lock);
2207
2208
20.5k
    free(r);
2209
20.5k
}
2210
2211
20.5k
static refs_t *refs_create(void) {
2212
20.5k
    refs_t *r = calloc(1, sizeof(*r));
2213
2214
20.5k
    RP("refs_create()\n");
2215
2216
20.5k
    if (!r)
2217
0
        return NULL;
2218
2219
20.5k
    if (!(r->pool = string_pool_create(8192)))
2220
0
        goto err;
2221
2222
20.5k
    r->ref_id = NULL; // see refs2id() to populate.
2223
20.5k
    r->count = 1;
2224
20.5k
    r->last = NULL;
2225
20.5k
    r->last_id = -1;
2226
2227
20.5k
    if (!(r->h_meta = kh_init(refs)))
2228
0
        goto err;
2229
2230
20.5k
    pthread_mutex_init(&r->lock, NULL);
2231
2232
20.5k
    return r;
2233
2234
0
 err:
2235
0
    refs_free(r);
2236
0
    return NULL;
2237
20.5k
}
2238
2239
/*
2240
 * Opens a reference fasta file as a BGZF stream, allowing for
2241
 * compressed files.  It automatically builds a .fai file if
2242
 * required and if compressed a .gzi bgzf index too.
2243
 *
2244
 * Returns a BGZF handle on success;
2245
 *         NULL on failure.
2246
 */
2247
1.31k
static BGZF *bgzf_open_ref(char *fn, char *mode, int is_md5) {
2248
1.31k
    BGZF *fp;
2249
2250
1.31k
    if (strncmp(fn, "file://", 7) == 0)
2251
2
        fn += 7;
2252
2253
1.31k
    if (!is_md5 && !hisremote(fn)) {
2254
984
        char fai_file[PATH_MAX];
2255
2256
984
        snprintf(fai_file, PATH_MAX, "%s.fai", fn);
2257
984
        if (access(fai_file, R_OK) != 0)
2258
984
            if (fai_build(fn) != 0)
2259
984
                return NULL;
2260
984
    }
2261
2262
330
    if (!(fp = bgzf_open(fn, mode))) {
2263
330
        perror(fn);
2264
330
        return NULL;
2265
330
    }
2266
2267
0
    if (fp->is_compressed == 1 && bgzf_index_load(fp, fn, ".gzi") < 0) {
2268
0
        hts_log_error("Unable to load .gzi index '%s.gzi'", fn);
2269
0
        bgzf_close(fp);
2270
0
        return NULL;
2271
0
    }
2272
2273
0
    return fp;
2274
0
}
2275
2276
/*
2277
 * Loads a FAI file for a reference.fasta.
2278
 * "is_err" indicates whether failure to load is worthy of emitting an
2279
 * error message. In some cases (eg with embedded references) we
2280
 * speculatively load, just in case, and silently ignore errors.
2281
 *
2282
 * Returns the refs_t struct on success (maybe newly allocated);
2283
 *         NULL on failure
2284
 */
2285
1.31k
static refs_t *refs_load_fai(refs_t *r_orig, const char *fn, int is_err) {
2286
1.31k
    hFILE *fp = NULL;
2287
1.31k
    char fai_fn[PATH_MAX];
2288
1.31k
    char line[8192];
2289
1.31k
    refs_t *r = r_orig;
2290
1.31k
    size_t fn_l = strlen(fn);
2291
1.31k
    int id = 0, id_alloc = 0;
2292
2293
1.31k
    RP("refs_load_fai %s\n", fn);
2294
2295
1.31k
    if (!r)
2296
0
        if (!(r = refs_create()))
2297
0
            goto err;
2298
2299
1.31k
    if (r->fp)
2300
0
        if (bgzf_close(r->fp) != 0)
2301
0
            goto err;
2302
1.31k
    r->fp = NULL;
2303
2304
    /* Look for a FASTA##idx##FAI format */
2305
1.31k
    const char *fn_delim = strstr(fn, HTS_IDX_DELIM);
2306
1.31k
    if (fn_delim) {
2307
25
        if (!(r->fn = string_ndup(r->pool, fn, fn_delim - fn)))
2308
0
            goto err;
2309
25
        fn_delim += strlen(HTS_IDX_DELIM);
2310
25
        snprintf(fai_fn, PATH_MAX, "%s", fn_delim);
2311
1.28k
    } else {
2312
        /* An index file was provided, instead of the actual reference file */
2313
1.28k
        if (fn_l > 4 && strcmp(&fn[fn_l-4], ".fai") == 0) {
2314
3
            if (!r->fn) {
2315
3
                if (!(r->fn = string_ndup(r->pool, fn, fn_l-4)))
2316
0
                    goto err;
2317
3
            }
2318
3
            snprintf(fai_fn, PATH_MAX, "%s", fn);
2319
1.28k
        } else {
2320
        /* Only the reference file provided. Get the index file name from it */
2321
1.28k
            if (!(r->fn = string_dup(r->pool, fn)))
2322
0
                goto err;
2323
1.28k
            snprintf(fai_fn, PATH_MAX, "%.*s.fai", PATH_MAX-5, fn);
2324
1.28k
        }
2325
1.28k
    }
2326
2327
1.31k
    if (!(r->fp = bgzf_open_ref(r->fn, "r", 0))) {
2328
1.31k
        hts_log_error("Failed to open reference file '%s'", r->fn);
2329
1.31k
        goto err;
2330
1.31k
    }
2331
2332
0
    if (!(fp = hopen(fai_fn, "r"))) {
2333
0
        hts_log_error("Failed to open index file '%s'", fai_fn);
2334
0
        if (is_err)
2335
0
            perror(fai_fn);
2336
0
        goto err;
2337
0
    }
2338
0
    while (hgets(line, 8192, fp) != NULL) {
2339
0
        ref_entry *e = malloc(sizeof(*e));
2340
0
        char *cp;
2341
0
        int n;
2342
0
        khint_t k;
2343
2344
0
        if (!e)
2345
0
            return NULL;
2346
2347
        // id
2348
0
        for (cp = line; *cp && !isspace_c(*cp); cp++)
2349
0
            ;
2350
0
        *cp++ = 0;
2351
0
        e->name = string_dup(r->pool, line);
2352
2353
        // length
2354
0
        while (*cp && isspace_c(*cp))
2355
0
            cp++;
2356
0
        e->length = strtoll(cp, &cp, 10);
2357
2358
        // offset
2359
0
        while (*cp && isspace_c(*cp))
2360
0
            cp++;
2361
0
        e->offset = strtoll(cp, &cp, 10);
2362
2363
        // bases per line
2364
0
        while (*cp && isspace_c(*cp))
2365
0
            cp++;
2366
0
        e->bases_per_line = strtol(cp, &cp, 10);
2367
2368
        // line length
2369
0
        while (*cp && isspace_c(*cp))
2370
0
            cp++;
2371
0
        e->line_length = strtol(cp, &cp, 10);
2372
2373
        // filename
2374
0
        e->fn = r->fn;
2375
2376
0
        e->count = 0;
2377
0
        e->seq = NULL;
2378
0
        e->mf = NULL;
2379
0
        e->is_md5 = 0;
2380
0
        e->validated_md5 = 0;
2381
2382
0
        k = kh_put(refs, r->h_meta, e->name, &n);
2383
0
        if (-1 == n)  {
2384
0
            free(e);
2385
0
            return NULL;
2386
0
        }
2387
2388
0
        if (n) {
2389
0
            kh_val(r->h_meta, k) = e;
2390
0
        } else {
2391
0
            ref_entry *re = kh_val(r->h_meta, k);
2392
0
            if (re && (re->count != 0 || re->length != 0)) {
2393
                /* Keep old */
2394
0
                free(e);
2395
0
            } else {
2396
                /* Replace old */
2397
0
                if (re)
2398
0
                    free(re);
2399
0
                kh_val(r->h_meta, k) = e;
2400
0
            }
2401
0
        }
2402
2403
0
        if (id >= id_alloc) {
2404
0
            ref_entry **new_refs;
2405
0
            int x;
2406
2407
0
            id_alloc = id_alloc ?id_alloc*2 : 16;
2408
0
            new_refs = hts_realloc_p(r->ref_id, sizeof(*r->ref_id), id_alloc);
2409
0
            if (!new_refs)
2410
0
                goto err;
2411
0
            r->ref_id = new_refs;
2412
2413
0
            for (x = id; x < id_alloc; x++)
2414
0
                r->ref_id[x] = NULL;
2415
0
        }
2416
0
        r->ref_id[id] = e;
2417
0
        r->nref = ++id;
2418
0
    }
2419
2420
0
    if(hclose(fp) < 0)
2421
0
        goto err;
2422
0
    return r;
2423
2424
1.31k
 err:
2425
1.31k
    if (fp)
2426
0
        hclose_abruptly(fp);
2427
2428
1.31k
    if (!r_orig)
2429
0
        refs_free(r);
2430
2431
1.31k
    return NULL;
2432
0
}
2433
2434
/*
2435
 * Verifies that the CRAM @SQ lines and .fai files match.
2436
 */
2437
0
static void sanitise_SQ_lines(cram_fd *fd) {
2438
0
    int i;
2439
2440
0
    if (!fd->header || !fd->header->hrecs)
2441
0
        return;
2442
2443
0
    if (!fd->refs || !fd->refs->h_meta)
2444
0
        return;
2445
2446
0
    for (i = 0; i < fd->header->hrecs->nref; i++) {
2447
0
        const char *name = fd->header->hrecs->ref[i].name;
2448
0
        khint_t k = kh_get(refs, fd->refs->h_meta, name);
2449
0
        ref_entry *r;
2450
2451
        // We may have @SQ lines which have no known .fai, but do not
2452
        // in themselves pose a problem because they are unused in the file.
2453
0
        if (k == kh_end(fd->refs->h_meta))
2454
0
            continue;
2455
2456
0
        if (!(r = (ref_entry *)kh_val(fd->refs->h_meta, k)))
2457
0
            continue;
2458
2459
0
        if (r->length && r->length != fd->header->hrecs->ref[i].len) {
2460
0
            assert(strcmp(r->name, fd->header->hrecs->ref[i].name) == 0);
2461
2462
            // Should we also check MD5sums here to ensure the correct
2463
            // reference was given?
2464
0
            hts_log_warning("Header @SQ length mismatch for ref %s, %"PRIhts_pos" vs %d",
2465
0
                            r->name, fd->header->hrecs->ref[i].len, (int)r->length);
2466
2467
            // Fixing the parsed @SQ header will make MD:Z: strings work
2468
            // and also stop it producing N for the sequence.
2469
0
            fd->header->hrecs->ref[i].len = r->length;
2470
0
        }
2471
0
    }
2472
0
}
2473
2474
/*
2475
 * Indexes references by the order they appear in a BAM file. This may not
2476
 * necessarily be the same order they appear in the fasta reference file.
2477
 *
2478
 * Returns 0 on success
2479
 *        -1 on failure
2480
 */
2481
10.2k
int refs2id(refs_t *r, sam_hdr_t *hdr) {
2482
10.2k
    int i;
2483
10.2k
    sam_hrecs_t *h = hdr->hrecs;
2484
2485
10.2k
    if (r->ref_id)
2486
3.35k
        free(r->ref_id);
2487
10.2k
    if (r->last)
2488
0
        r->last = NULL;
2489
2490
10.2k
    r->ref_id = calloc(h->nref, sizeof(*r->ref_id));
2491
10.2k
    if (!r->ref_id)
2492
0
        return -1;
2493
2494
10.2k
    r->nref = h->nref;
2495
14.7k
    for (i = 0; i < h->nref; i++) {
2496
4.48k
        khint_t k = kh_get(refs, r->h_meta, h->ref[i].name);
2497
4.48k
        if (k != kh_end(r->h_meta)) {
2498
4.48k
            r->ref_id[i] = kh_val(r->h_meta, k);
2499
4.48k
        } else {
2500
0
            hts_log_warning("Unable to find ref name '%s'", h->ref[i].name);
2501
0
        }
2502
4.48k
    }
2503
2504
10.2k
    return 0;
2505
10.2k
}
2506
2507
/*
2508
 * Generates refs_t entries based on @SQ lines in the header.
2509
 * Returns 0 on success
2510
 *         -1 on failure
2511
 */
2512
41.1k
static int refs_from_header(cram_fd *fd) {
2513
41.1k
    if (!fd)
2514
0
        return -1;
2515
2516
41.1k
    refs_t *r = fd->refs;
2517
41.1k
    if (!r)
2518
0
        return -1;
2519
2520
41.1k
    sam_hdr_t *h = fd->header;
2521
41.1k
    if (!h)
2522
11.0k
        return 0;
2523
2524
30.1k
    if (!h->hrecs) {
2525
19.1k
        if (-1 == sam_hdr_fill_hrecs(h))
2526
109
            return -1;
2527
19.1k
    }
2528
2529
30.0k
    if (h->hrecs->nref == 0)
2530
23.0k
        return 0;
2531
2532
    //fprintf(stderr, "refs_from_header for %p mode %c\n", fd, fd->mode);
2533
2534
    /* Existing refs are fine, as long as they're compatible with the hdr. */
2535
7.01k
    ref_entry **new_ref_id = hts_realloc_ps(r->ref_id, sizeof(*r->ref_id),
2536
7.01k
                                            r->nref, h->hrecs->nref);
2537
7.01k
    if (!new_ref_id)
2538
0
        return -1;
2539
7.01k
    r->ref_id = new_ref_id;
2540
2541
7.01k
    int i, j;
2542
    /* Copy info from h->ref[i] over to r */
2543
17.2k
    for (i = 0, j = r->nref; i < h->hrecs->nref; i++) {
2544
10.2k
        sam_hrec_type_t *ty;
2545
10.2k
        sam_hrec_tag_t *tag;
2546
10.2k
        khint_t k;
2547
10.2k
        int n;
2548
2549
10.2k
        k = kh_get(refs, r->h_meta, h->hrecs->ref[i].name);
2550
10.2k
        if (k != kh_end(r->h_meta))
2551
            // Ref already known about
2552
4.48k
            continue;
2553
2554
5.79k
        if (!(r->ref_id[j] = calloc(1, sizeof(ref_entry))))
2555
0
            return -1;
2556
2557
5.79k
        if (!h->hrecs->ref[i].name)
2558
0
            return -1;
2559
2560
5.79k
        r->ref_id[j]->name = string_dup(r->pool, h->hrecs->ref[i].name);
2561
5.79k
        if (!r->ref_id[j]->name) return -1;
2562
5.79k
        r->ref_id[j]->length = 0; // marker for not yet loaded
2563
2564
        /* Initialise likely filename if known */
2565
5.79k
        if ((ty = sam_hrecs_find_type_id(h->hrecs, "SQ", "SN", h->hrecs->ref[i].name))) {
2566
5.79k
            if ((tag = sam_hrecs_find_key(ty, "M5", NULL)))
2567
228
                r->ref_id[j]->fn = string_dup(r->pool, tag->str+3);
2568
2569
5.79k
            if ((tag = sam_hrecs_find_key(ty, "LN", NULL))) {
2570
                // LN tag used when constructing consensus reference
2571
5.79k
                r->ref_id[j]->LN_length = strtoll(tag->str+3, NULL, 0);
2572
                // See fuzz 382922241
2573
5.79k
                if (r->ref_id[j]->LN_length < 0)
2574
1
                    r->ref_id[j]->LN_length = 0;
2575
5.79k
            }
2576
5.79k
        }
2577
2578
5.79k
        k = kh_put(refs, r->h_meta, r->ref_id[j]->name, &n);
2579
5.79k
        if (n <= 0) // already exists or error
2580
0
            return -1;
2581
5.79k
        kh_val(r->h_meta, k) = r->ref_id[j];
2582
2583
5.79k
        j++;
2584
5.79k
    }
2585
7.01k
    r->nref = j;
2586
2587
7.01k
    return 0;
2588
7.01k
}
2589
2590
/*
2591
 * Attaches a header to a cram_fd.
2592
 *
2593
 * This should be used when creating a new cram_fd for writing where
2594
 * we have a header already constructed (eg from a file we've read
2595
 * in).
2596
 */
2597
10.3k
int cram_set_header2(cram_fd *fd, const sam_hdr_t *hdr) {
2598
10.3k
    if (!fd || !hdr )
2599
0
        return -1;
2600
2601
10.3k
    if (fd->header != hdr) {
2602
10.3k
        if (fd->header)
2603
0
            sam_hdr_destroy(fd->header);
2604
10.3k
        fd->header = sam_hdr_dup(hdr);
2605
10.3k
        if (!fd->header)
2606
0
            return -1;
2607
10.3k
    }
2608
10.3k
    return refs_from_header(fd);
2609
10.3k
}
2610
2611
0
int cram_set_header(cram_fd *fd, sam_hdr_t *hdr) {
2612
0
    return cram_set_header2(fd, hdr);
2613
0
}
2614
2615
/*
2616
 * Returns whether the path refers to a directory.
2617
 */
2618
0
static int is_directory(char *fn) {
2619
0
    struct stat buf;
2620
0
    if ( stat(fn,&buf) ) return 0;
2621
0
    return S_ISDIR(buf.st_mode);
2622
0
}
2623
2624
/*
2625
 * Converts a directory and a filename into an expanded path, replacing %s
2626
 * in directory with the filename and %[0-9]+s with portions of the filename
2627
 * Any remaining parts of filename are added to the end with /%s.
2628
 */
2629
0
static int expand_cache_path(char *path, char *dir, const char *fn) {
2630
0
    char *cp, *start = path;
2631
0
    size_t len;
2632
0
    size_t sz = PATH_MAX;
2633
2634
0
    while ((cp = strchr(dir, '%'))) {
2635
0
        if (cp-dir >= sz) return -1;
2636
0
        strncpy(path, dir, cp-dir);
2637
0
        path += cp-dir;
2638
0
        sz -= cp-dir;
2639
2640
0
        if (*++cp == 's') {
2641
0
            len = strlen(fn);
2642
0
            if (len >= sz) return -1;
2643
0
            strcpy(path, fn);
2644
0
            path += len;
2645
0
            sz -= len;
2646
0
            fn += len;
2647
0
            cp++;
2648
0
        } else if (*cp >= '0' && *cp <= '9') {
2649
0
            char *endp;
2650
0
            long l;
2651
2652
0
            l = strtol(cp, &endp, 10);
2653
0
            l = MIN(l, strlen(fn));
2654
0
            if (*endp == 's') {
2655
0
                if (l >= sz) return -1;
2656
0
                strncpy(path, fn, l);
2657
0
                path += l;
2658
0
                fn += l;
2659
0
                sz -= l;
2660
0
                *path = 0;
2661
0
                cp = endp+1;
2662
0
            } else {
2663
0
                if (sz < 3) return -1;
2664
0
                *path++ = '%';
2665
0
                *path++ = *cp++;
2666
0
            }
2667
0
        } else {
2668
0
            if (sz < 3) return -1;
2669
0
            *path++ = '%';
2670
0
            *path++ = *cp++;
2671
0
        }
2672
0
        dir = cp;
2673
0
    }
2674
2675
0
    len = strlen(dir);
2676
0
    if (len >= sz) return -1;
2677
0
    strcpy(path, dir);
2678
0
    path += len;
2679
0
    sz -= len;
2680
2681
0
    len = strlen(fn) + ((*fn && path > start && path[-1] != '/') ? 1 : 0);
2682
0
    if (len >= sz) return -1;
2683
0
    if (*fn && path > start && path[-1] != '/')
2684
0
        *path++ = '/';
2685
0
    strcpy(path, fn);
2686
0
    return 0;
2687
0
}
2688
2689
/*
2690
 * Make the directory containing path and any prefix directories.
2691
 */
2692
0
static void mkdir_prefix(char *path, int mode) {
2693
0
    char *cp = strrchr(path, '/');
2694
0
    if (!cp)
2695
0
        return;
2696
2697
0
    *cp = 0;
2698
0
    if (is_directory(path)) {
2699
0
        *cp = '/';
2700
0
        return;
2701
0
    }
2702
2703
0
    if (mkdir(path, mode) == 0) {
2704
0
        chmod(path, mode);
2705
0
        *cp = '/';
2706
0
        return;
2707
0
    }
2708
2709
0
    mkdir_prefix(path, mode);
2710
0
    mkdir(path, mode);
2711
0
    chmod(path, mode);
2712
0
    *cp = '/';
2713
0
}
2714
2715
/*
2716
 * Queries the M5 string from the header and attempts to populate the
2717
 * reference from this using the REF_PATH environment.
2718
 *
2719
 * Returns 0 on success
2720
 *        -1 on failure
2721
 */
2722
3.42k
static int cram_populate_ref(cram_fd *fd, int id, ref_entry *r) {
2723
3.42k
    char *ref_path = getenv("REF_PATH");
2724
3.42k
    sam_hrec_type_t *ty;
2725
3.42k
    sam_hrec_tag_t *tag;
2726
3.42k
    char path[PATH_MAX];
2727
3.42k
    kstring_t path_tmp = KS_INITIALIZE;
2728
3.42k
    char *local_cache = getenv("REF_CACHE");
2729
3.42k
    mFILE *mf;
2730
3.42k
    int local_path = 0;
2731
2732
3.42k
    hts_log_info("Running cram_populate_ref on fd %p, id %d", (void *)fd, id);
2733
2734
3.42k
    if (!r->name)
2735
0
        return -1;
2736
2737
3.42k
    if (!(ty = sam_hrecs_find_type_id(fd->header->hrecs, "SQ", "SN", r->name)))
2738
0
        return -1;
2739
2740
3.42k
    if (!(tag = sam_hrecs_find_key(ty, "M5", NULL)))
2741
3.41k
        goto no_M5;
2742
2743
9
    hts_log_info("Querying ref %s", tag->str+3);
2744
2745
    /* Use cache if available */
2746
9
    if (local_cache && *local_cache) {
2747
0
        struct stat sb;
2748
0
        if (expand_cache_path(path, local_cache, tag->str+3) == 0 &&
2749
0
            stat(path, &sb) == 0)
2750
            // Found it in the local cache
2751
0
            local_path = 1;
2752
0
    }
2753
2754
#ifndef HAVE_MMAP
2755
    char *path2;
2756
    /* Search local files in REF_PATH; we can open them and return as above */
2757
    if (!local_path && (path2 = find_path(tag->str+3, ref_path))) {
2758
        int len = snprintf(path, PATH_MAX, "%s", path2);
2759
        free(path2);
2760
        if (len > 0 && len < PATH_MAX) // in case it's too long
2761
            local_path = 1;
2762
    }
2763
#endif
2764
2765
    /* Found via REF_CACHE or local REF_PATH file */
2766
9
    if (local_path) {
2767
0
        struct stat sb;
2768
0
        BGZF *fp;
2769
2770
0
        if (0 == stat(path, &sb)
2771
0
            && S_ISREG(sb.st_mode)
2772
0
            && (fp = bgzf_open(path, "r"))) {
2773
0
            r->length = sb.st_size;
2774
0
            r->offset = r->line_length = r->bases_per_line = 0;
2775
2776
0
            r->fn = string_dup(fd->refs->pool, path);
2777
2778
0
            if (fd->refs->fp)
2779
0
                if (bgzf_close(fd->refs->fp) != 0)
2780
0
                    return -1;
2781
0
            fd->refs->fp = fp;
2782
0
            fd->refs->fn = r->fn;
2783
0
            r->is_md5 = 1;
2784
0
            r->validated_md5 = 1;
2785
2786
            // Fall back to cram_get_ref() where it'll do the actual
2787
            // reading of the file.
2788
0
            return 0;
2789
0
        }
2790
0
    }
2791
2792
2793
    /* Otherwise search full REF_PATH; slower as loads entire file */
2794
9
    int is_local = 0;
2795
9
    if ((mf = open_path_mfile(tag->str+3, ref_path, NULL, &is_local))) {
2796
0
        size_t sz;
2797
0
        r->seq = mfsteal(mf, &sz);
2798
0
        if (r->seq) {
2799
0
            r->mf = NULL;
2800
0
        } else {
2801
            // keep mf around as we couldn't detach
2802
0
            r->seq = mf->data;
2803
0
            r->mf = mf;
2804
0
        }
2805
0
        r->length = sz;
2806
0
        r->is_md5 = 1;
2807
0
        r->validated_md5 = 1;
2808
9
    } else {
2809
9
        refs_t *refs;
2810
9
        const char *fn;
2811
9
        sam_hrec_tag_t *UR_tag;
2812
2813
3.42k
    no_M5:
2814
        /* Failed to find in search path or M5 cache, see if @SQ UR: tag? */
2815
3.42k
        if (!(UR_tag = sam_hrecs_find_key(ty, "UR", NULL)))
2816
2.10k
            return -1;
2817
2818
1.32k
        if (strstr(UR_tag->str+3, "://") &&
2819
108
            strncmp(UR_tag->str+3, "file:", 5) != 0) {
2820
            // Documented as omitted, but accidentally supported until now
2821
13
            hts_log_error("UR tags pointing to remote files are not supported");
2822
13
            return -1;
2823
13
        }
2824
2825
1.31k
        fn = (strncmp(UR_tag->str+3, "file:", 5) == 0)
2826
1.31k
            ? UR_tag->str+8
2827
1.31k
            : UR_tag->str+3;
2828
2829
1.31k
        if (fd->refs->fp) {
2830
0
            if (bgzf_close(fd->refs->fp) != 0)
2831
0
                return -1;
2832
0
            fd->refs->fp = NULL;
2833
0
        }
2834
1.31k
        if (!(refs = refs_load_fai(fd->refs, fn, 0)))
2835
1.31k
            return -1;
2836
0
        sanitise_SQ_lines(fd);
2837
2838
0
        fd->refs = refs;
2839
0
        if (fd->refs->fp) {
2840
0
            if (bgzf_close(fd->refs->fp) != 0)
2841
0
                return -1;
2842
0
            fd->refs->fp = NULL;
2843
0
        }
2844
2845
0
        if (!fd->refs->fn)
2846
0
            return -1;
2847
2848
0
        if (-1 == refs2id(fd->refs, fd->header))
2849
0
            return -1;
2850
0
        if (!fd->refs->ref_id || !fd->refs->ref_id[id])
2851
0
            return -1;
2852
2853
        // Local copy already, so fall back to cram_get_ref().
2854
0
        return 0;
2855
0
    }
2856
2857
    /* Populate the local disk cache if required */
2858
0
    if (!is_local && local_cache && *local_cache) {
2859
0
        hFILE *fp;
2860
2861
0
        if (expand_cache_path(path, local_cache, tag->str+3) < 0) {
2862
0
            return 0; // Not fatal - we have the data already so keep going.
2863
0
        }
2864
0
        hts_log_info("Writing cache file '%s'", path);
2865
0
        mkdir_prefix(path, 01777);
2866
2867
0
        fp = hts_open_tmpfile(path, "wx", &path_tmp);
2868
0
        if (!fp) {
2869
0
            perror(path_tmp.s);
2870
0
            free(path_tmp.s);
2871
2872
            // Not fatal - we have the data already so keep going.
2873
0
            return 0;
2874
0
        }
2875
2876
        // Check md5sum
2877
0
        hts_md5_context *md5;
2878
0
        char unsigned md5_buf1[16];
2879
0
        char md5_buf2[33];
2880
2881
0
        if (!(md5 = hts_md5_init())) {
2882
0
            hclose_abruptly(fp);
2883
0
            unlink(path_tmp.s);
2884
0
            free(path_tmp.s);
2885
0
            return -1;
2886
0
        }
2887
0
        hts_md5_update(md5, r->seq, r->length);
2888
0
        hts_md5_final(md5_buf1, md5);
2889
0
        hts_md5_destroy(md5);
2890
0
        hts_md5_hex(md5_buf2, md5_buf1);
2891
2892
0
        if (strncmp(tag->str+3, md5_buf2, 32) != 0) {
2893
0
            hts_log_error("Mismatching md5sum for downloaded reference");
2894
0
            hclose_abruptly(fp);
2895
0
            unlink(path_tmp.s);
2896
0
            free(path_tmp.s);
2897
0
            return -1;
2898
0
        }
2899
2900
0
        ssize_t length_written = hwrite(fp, r->seq, r->length);
2901
0
        if (hclose(fp) < 0 || length_written != r->length ||
2902
0
            chmod(path_tmp.s, 0444) < 0 ||
2903
0
            rename(path_tmp.s, path) < 0) {
2904
0
            hts_log_error("Creating reference at %s failed: %s",
2905
0
                          path, strerror(errno));
2906
0
            unlink(path_tmp.s);
2907
0
        }
2908
0
    }
2909
2910
0
    free(path_tmp.s);
2911
0
    return 0;
2912
0
}
2913
2914
1.61k
static void cram_ref_incr_locked(refs_t *r, int id) {
2915
1.61k
    RP("%d INC REF %d, %d %p\n", gettid(), id,
2916
1.61k
       (int)(id>=0 && r->ref_id[id]?r->ref_id[id]->count+1:-999),
2917
1.61k
       id>=0 && r->ref_id[id]?r->ref_id[id]->seq:(char *)1);
2918
2919
1.61k
    if (id < 0 || !r->ref_id[id] || !r->ref_id[id]->seq)
2920
1.61k
        return;
2921
2922
0
    if (r->last_id == id)
2923
0
        r->last_id = -1;
2924
2925
0
    ++r->ref_id[id]->count;
2926
0
}
2927
2928
1.61k
void cram_ref_incr(refs_t *r, int id) {
2929
1.61k
    pthread_mutex_lock(&r->lock);
2930
1.61k
    cram_ref_incr_locked(r, id);
2931
1.61k
    pthread_mutex_unlock(&r->lock);
2932
1.61k
}
2933
2934
74
static void cram_ref_decr_locked(refs_t *r, int id) {
2935
74
    RP("%d DEC REF %d, %d %p\n", gettid(), id,
2936
74
       (int)(id>=0 && r->ref_id[id]?r->ref_id[id]->count-1:-999),
2937
74
       id>=0 && r->ref_id[id]?r->ref_id[id]->seq:(char *)1);
2938
2939
74
    if (id < 0 || !r->ref_id[id] || !r->ref_id[id]->seq) {
2940
74
        return;
2941
74
    }
2942
2943
0
    if (--r->ref_id[id]->count <= 0) {
2944
0
        assert(r->ref_id[id]->count == 0);
2945
0
        if (r->last_id >= 0) {
2946
0
            if (r->ref_id[r->last_id]->count <= 0 &&
2947
0
                r->ref_id[r->last_id]->seq) {
2948
0
                RP("%d FREE REF %d (%p)\n", gettid(),
2949
0
                   r->last_id, r->ref_id[r->last_id]->seq);
2950
0
                ref_entry_free_seq(r->ref_id[r->last_id]);
2951
0
                if (r->ref_id[r->last_id]->is_md5) r->ref_id[r->last_id]->length = 0;
2952
0
            }
2953
0
        }
2954
0
        r->last_id = id;
2955
0
    }
2956
0
}
2957
2958
74
void cram_ref_decr(refs_t *r, int id) {
2959
74
    pthread_mutex_lock(&r->lock);
2960
74
    cram_ref_decr_locked(r, id);
2961
74
    pthread_mutex_unlock(&r->lock);
2962
74
}
2963
2964
/*
2965
 * Used by cram_ref_load and cram_get_ref. The file handle will have
2966
 * already been opened, so we can catch it. The ref_entry *e informs us
2967
 * of whether this is a multi-line fasta file or a raw MD5 style file.
2968
 * Either way we create a single contiguous sequence.
2969
 *
2970
 * Returns all or part of a reference sequence on success (malloced);
2971
 *         NULL on failure.
2972
 */
2973
static char *load_ref_portion(BGZF *fp, ref_entry *e,
2974
0
                              hts_pos_t start, hts_pos_t end) {
2975
0
    off_t offset, len;
2976
0
    char *seq;
2977
2978
0
    if (end < start)
2979
0
        end = start;
2980
2981
    /*
2982
     * Compute locations in file. This is trivial for the MD5 files, but
2983
     * is still necessary for the fasta variants.
2984
     *
2985
     * Note the offset here, as with faidx, has the assumption that white-
2986
     * space (the diff between line_length and bases_per_line) only occurs
2987
     * at the end of a line of text.
2988
     */
2989
0
    offset = e->line_length
2990
0
        ? e->offset + (start-1)/e->bases_per_line * e->line_length +
2991
0
          (start-1) % e->bases_per_line
2992
0
        : start-1;
2993
2994
0
    len = (e->line_length
2995
0
           ? e->offset + (end-1)/e->bases_per_line * e->line_length +
2996
0
             (end-1) % e->bases_per_line
2997
0
           : end-1) - offset + 1;
2998
2999
0
    if (bgzf_useek(fp, offset, SEEK_SET) < 0) {
3000
0
        perror("bgzf_useek() on reference file");
3001
0
        return NULL;
3002
0
    }
3003
3004
0
    if (len == 0 || !(seq = malloc(len))) {
3005
0
        return NULL;
3006
0
    }
3007
3008
0
    if (len != bgzf_read(fp, seq, len)) {
3009
0
        perror("bgzf_read() on reference file");
3010
0
        free(seq);
3011
0
        return NULL;
3012
0
    }
3013
3014
    /* Strip white-space if required. */
3015
0
    if (len != end-start+1) {
3016
0
        hts_pos_t i, j;
3017
0
        char *cp = seq;
3018
0
        char *cp_to;
3019
3020
        // Copy up to the first white-space, and then repeatedly just copy
3021
        // bases_per_line verbatim, and use the slow method to end again.
3022
        //
3023
        // This may seem excessive, but this code can be a significant
3024
        // portion of total CRAM decode CPU time for shallow data sets.
3025
0
        for (i = j = 0; i < len; i++) {
3026
0
            if (!isspace_c(cp[i]))
3027
0
                cp[j++] = cp[i] & ~0x20;
3028
0
            else
3029
0
                break;
3030
0
        }
3031
0
        while (i < len && isspace_c(cp[i]))
3032
0
            i++;
3033
0
        while (i < len - e->line_length) {
3034
0
            hts_pos_t j_end = j + e->bases_per_line;
3035
0
            while (j < j_end)
3036
0
                cp[j++] = cp[i++] & ~0x20; // toupper equiv
3037
0
            i += e->line_length - e->bases_per_line;
3038
0
        }
3039
0
        for (; i < len; i++) {
3040
0
            if (!isspace_c(cp[i]))
3041
0
                cp[j++] = cp[i] & ~0x20;
3042
0
        }
3043
3044
0
        cp_to = cp+j;
3045
3046
0
        if (cp_to - seq != end-start+1) {
3047
0
            hts_log_error("Malformed reference file");
3048
0
            free(seq);
3049
0
            return NULL;
3050
0
        }
3051
0
    } else {
3052
0
        int i;
3053
0
        for (i = 0; i < len; i++) {
3054
0
            seq[i] = toupper_c(seq[i]);
3055
0
        }
3056
0
    }
3057
3058
0
    return seq;
3059
0
}
3060
3061
/*
3062
 * Load the entire reference 'id'.
3063
 * This also increments the reference count by 1.
3064
 *
3065
 * Returns ref_entry on success;
3066
 *         NULL on failure
3067
 */
3068
0
ref_entry *cram_ref_load(refs_t *r, int id, int is_md5) {
3069
0
    ref_entry *e = r->ref_id[id];
3070
0
    hts_pos_t start = 1, end = e->length;
3071
0
    char *seq;
3072
3073
0
    if (e->seq) {
3074
0
        return e;
3075
0
    }
3076
3077
0
    assert(e->count == 0);
3078
3079
0
    if (r->last) {
3080
#ifdef REF_DEBUG
3081
        int idx = 0;
3082
        for (idx = 0; idx < r->nref; idx++)
3083
            if (r->last == r->ref_id[idx])
3084
                break;
3085
        RP("%d cram_ref_load DECR %d\n", gettid(), idx);
3086
#endif
3087
0
        assert(r->last->count > 0);
3088
0
        if (--r->last->count <= 0) {
3089
0
            RP("%d FREE REF %d (%p)\n", gettid(), id, r->ref_id[id]->seq);
3090
0
            if (r->last->seq)
3091
0
                ref_entry_free_seq(r->last);
3092
0
        }
3093
0
    }
3094
3095
0
    if (!r->fn)
3096
0
        return NULL;
3097
3098
    /* Open file if it's not already the current open reference */
3099
0
    if (strcmp(r->fn, e->fn) || r->fp == NULL) {
3100
0
        if (r->fp)
3101
0
            if (bgzf_close(r->fp) != 0)
3102
0
                return NULL;
3103
0
        r->fn = e->fn;
3104
0
        if (!(r->fp = bgzf_open_ref(r->fn, "r", is_md5)))
3105
0
            return NULL;
3106
0
    }
3107
3108
0
    RP("%d Loading ref %d (%d..%d)\n", gettid(), id, start, end);
3109
3110
0
    if (!(seq = load_ref_portion(r->fp, e, start, end))) {
3111
0
        return NULL;
3112
0
    }
3113
3114
0
    RP("%d Loaded ref %d (%d..%d) = %p\n", gettid(), id, start, end, seq);
3115
3116
0
    RP("%d INC REF %d, %"PRId64"\n", gettid(), id, (e->count+1));
3117
0
    e->seq = seq;
3118
0
    e->mf = NULL;
3119
0
    e->count++;
3120
3121
    /*
3122
     * Also keep track of last used ref so incr/decr loops on the same
3123
     * sequence don't cause load/free loops.
3124
     */
3125
0
    RP("%d cram_ref_load INCR %d => %"PRId64"\n", gettid(), id, e->count+1);
3126
0
    r->last = e;
3127
0
    e->count++;
3128
3129
0
    return e;
3130
0
}
3131
3132
/*
3133
 * Returns a portion of a reference sequence from start to end inclusive.
3134
 * The returned pointer is owned by either the cram_file fd or by the
3135
 * internal refs_t structure and should not be freed  by the caller.
3136
 *
3137
 * The difference is whether or not this refs_t is in use by just the one
3138
 * cram_fd or by multiples, or whether we have multiple threads accessing
3139
 * references. In either case fd->shared will be true and we start using
3140
 * reference counting to track the number of users of a specific reference
3141
 * sequence.
3142
 *
3143
 * Otherwise the ref seq returned is allocated as part of cram_fd itself
3144
 * and will be freed up on the next call to cram_get_ref or cram_close.
3145
 *
3146
 * To return the entire reference sequence, specify start as 1 and end
3147
 * as 0.
3148
 *
3149
 * To cease using a reference, call cram_ref_decr().
3150
 *
3151
 * Returns reference on success,
3152
 *         NULL on failure
3153
 */
3154
7.90k
char *cram_get_ref(cram_fd *fd, int id, hts_pos_t start, hts_pos_t end) {
3155
7.90k
    ref_entry *r;
3156
7.90k
    char *seq;
3157
7.90k
    int ostart = start;
3158
3159
7.90k
    if (id == -1 || start < 1)
3160
4.45k
        return NULL;
3161
3162
    /* FIXME: axiomatic query of r->seq being true?
3163
     * Or shortcut for unsorted data where we load once and never free?
3164
     */
3165
3166
    //fd->shared_ref = 1; // hard code for now to simplify things
3167
3168
3.44k
    pthread_mutex_lock(&fd->ref_lock);
3169
3170
3.44k
    RP("%d cram_get_ref on fd %p, id %d, range %d..%d\n", gettid(), fd, id, start, end);
3171
3172
    /*
3173
     * Unsorted data implies we want to fetch an entire reference at a time.
3174
     * We just deal with this at the moment by claiming we're sharing
3175
     * references instead, which has the same requirement.
3176
     */
3177
3.44k
    if (fd->unsorted)
3178
0
        fd->shared_ref = 1;
3179
3180
3181
    /* Sanity checking: does this ID exist? */
3182
3.44k
    if (!fd->refs || id < 0 || id >= fd->refs->nref || !fd->refs->ref_id[id]) {
3183
21
        hts_log_error("No reference found for id %d", id);
3184
21
        pthread_mutex_unlock(&fd->ref_lock);
3185
21
        return NULL;
3186
21
    }
3187
3188
3.42k
    r = fd->refs->ref_id[id];
3189
3190
    /*
3191
     * It has an entry, but may not have been populated yet.
3192
     * Any manually loaded .fai files have their lengths known.
3193
     * A ref entry computed from @SQ lines (M5 or UR field) will have
3194
     * r->length == 0 unless it's been loaded once and verified that we have
3195
     * an on-disk filename for it.
3196
     *
3197
     * 19 Sep 2013: Moved the lock here as the cram_populate_ref code calls
3198
     * open_path_mfile and libcurl, which isn't multi-thread safe unless I
3199
     * rewrite my code to have one curl handle per thread.
3200
     */
3201
3.42k
    pthread_mutex_lock(&fd->refs->lock);
3202
3.42k
    if (r->length == 0) {
3203
3.42k
        if (fd->ref_fn)
3204
0
            hts_log_warning("Reference file given, but ref '%s' not present",
3205
3.42k
                            r->name);
3206
3.42k
        if (cram_populate_ref(fd, id, r) == -1) {
3207
3.42k
            hts_log_warning("Failed to populate reference \"%s\"",
3208
3.42k
                            r->name);
3209
3.42k
            hts_log_warning("See https://www.htslib.org/doc/reference_seqs.html for further suggestions");
3210
3.42k
            pthread_mutex_unlock(&fd->refs->lock);
3211
3.42k
            pthread_mutex_unlock(&fd->ref_lock);
3212
3.42k
            return NULL;
3213
3.42k
        }
3214
0
        r = fd->refs->ref_id[id];
3215
0
        if (fd->unsorted)
3216
0
            cram_ref_incr_locked(fd->refs, id);
3217
0
    }
3218
3219
3220
    /*
3221
     * We now know that we the filename containing the reference, so check
3222
     * for limits. If it's over half the reference we'll load all of it in
3223
     * memory as this will speed up subsequent calls.
3224
     */
3225
0
    if (end < 1)
3226
0
        end = r->length;
3227
0
    if (end >= r->length)
3228
0
        end  = r->length;
3229
3230
0
    if (end - start >= 0.5*r->length || fd->shared_ref) {
3231
0
        start = 1;
3232
0
        end = r->length;
3233
0
    }
3234
3235
    /*
3236
     * Maybe we have it cached already? If so use it.
3237
     *
3238
     * Alternatively if we don't have the sequence but we're sharing
3239
     * references and/or are asking for the entire length of it, then
3240
     * load the full reference into the refs structure and return
3241
     * a pointer to that one instead.
3242
     */
3243
0
    if (fd->shared_ref || r->seq || (start == 1 && end == r->length)) {
3244
0
        char *cp;
3245
3246
0
        if (id >= 0) {
3247
0
            if (r->seq) {
3248
0
                cram_ref_incr_locked(fd->refs, id);
3249
0
            } else {
3250
0
                ref_entry *e;
3251
0
                if (!(e = cram_ref_load(fd->refs, id, r->is_md5))) {
3252
0
                    pthread_mutex_unlock(&fd->refs->lock);
3253
0
                    pthread_mutex_unlock(&fd->ref_lock);
3254
0
                    return NULL;
3255
0
                }
3256
3257
                /* unsorted data implies cache ref indefinitely, to avoid
3258
                 * continually loading and unloading.
3259
                 */
3260
0
                if (fd->unsorted)
3261
0
                    cram_ref_incr_locked(fd->refs, id);
3262
0
            }
3263
3264
0
            fd->ref = NULL; /* We never access it directly */
3265
0
            fd->ref_start = 1;
3266
0
            fd->ref_end   = r->length;
3267
0
            fd->ref_id    = id;
3268
3269
0
            cp = fd->refs->ref_id[id]->seq + ostart-1;
3270
0
        } else {
3271
0
            fd->ref = NULL;
3272
0
            cp = NULL;
3273
0
        }
3274
3275
0
        RP("%d cram_get_ref returning for id %d, count %d\n", gettid(), id, (int)r->count);
3276
3277
0
        pthread_mutex_unlock(&fd->refs->lock);
3278
0
        pthread_mutex_unlock(&fd->ref_lock);
3279
0
        return cp;
3280
0
    }
3281
3282
    /*
3283
     * Otherwise we're not sharing, we don't have a copy of it already and
3284
     * we're only asking for a small portion of it.
3285
     *
3286
     * In this case load up just that segment ourselves, freeing any old
3287
     * small segments in the process.
3288
     */
3289
3290
    /* Unmapped ref ID */
3291
0
    if (id < 0 || !fd->refs->fn) {
3292
0
        if (fd->ref_free) {
3293
0
            free(fd->ref_free);
3294
0
            fd->ref_free = NULL;
3295
0
        }
3296
0
        fd->ref = NULL;
3297
0
        fd->ref_id = id;
3298
0
        pthread_mutex_unlock(&fd->refs->lock);
3299
0
        pthread_mutex_unlock(&fd->ref_lock);
3300
0
        return NULL;
3301
0
    }
3302
3303
    /* Open file if it's not already the current open reference */
3304
0
    if (strcmp(fd->refs->fn, r->fn) || fd->refs->fp == NULL) {
3305
0
        if (fd->refs->fp)
3306
0
            if (bgzf_close(fd->refs->fp) != 0)
3307
0
                return NULL;
3308
0
        fd->refs->fn = r->fn;
3309
0
        if (!(fd->refs->fp = bgzf_open_ref(fd->refs->fn, "r", r->is_md5))) {
3310
0
            pthread_mutex_unlock(&fd->refs->lock);
3311
0
            pthread_mutex_unlock(&fd->ref_lock);
3312
0
            return NULL;
3313
0
        }
3314
0
    }
3315
3316
0
    if (!(fd->ref = load_ref_portion(fd->refs->fp, r, start, end))) {
3317
0
        pthread_mutex_unlock(&fd->refs->lock);
3318
0
        pthread_mutex_unlock(&fd->ref_lock);
3319
0
        return NULL;
3320
0
    }
3321
3322
0
    if (fd->ref_free)
3323
0
        free(fd->ref_free);
3324
3325
0
    fd->ref_id    = id;
3326
0
    fd->ref_start = start;
3327
0
    fd->ref_end   = end;
3328
0
    fd->ref_free = fd->ref;
3329
0
    seq = fd->ref;
3330
3331
0
    pthread_mutex_unlock(&fd->refs->lock);
3332
0
    pthread_mutex_unlock(&fd->ref_lock);
3333
3334
0
    return seq ? seq + ostart - start : NULL;
3335
0
}
3336
3337
/*
3338
 * If fd has been opened for reading, it may be permitted to specify 'fn'
3339
 * as NULL and let the code auto-detect the reference by parsing the
3340
 * SAM header @SQ lines.
3341
 */
3342
0
int cram_load_reference(cram_fd *fd, char *fn) {
3343
0
    int ret = 0;
3344
3345
0
    if (fn) {
3346
0
        fd->refs = refs_load_fai(fd->refs, fn,
3347
0
                                 !(fd->embed_ref>0 && fd->mode == 'r'));
3348
0
        fn = fd->refs ? fd->refs->fn : NULL;
3349
0
        if (!fn)
3350
0
            ret = -1;
3351
0
        sanitise_SQ_lines(fd);
3352
0
    }
3353
0
    fd->ref_fn = fn;
3354
3355
0
    if ((!fd->refs || (fd->refs->nref == 0 && !fn)) && fd->header) {
3356
0
        if (fd->refs)
3357
0
            refs_free(fd->refs);
3358
0
        if (!(fd->refs = refs_create()))
3359
0
            return -1;
3360
0
        if (-1 == refs_from_header(fd))
3361
0
            return -1;
3362
0
    }
3363
3364
0
    if (fd->header)
3365
0
        if (-1 == refs2id(fd->refs, fd->header))
3366
0
            return -1;
3367
3368
0
    return ret;
3369
0
}
3370
3371
/* ----------------------------------------------------------------------
3372
 * Containers
3373
 */
3374
3375
/*
3376
 * Creates a new container, specifying the maximum number of slices
3377
 * and records permitted.
3378
 *
3379
 * Returns cram_container ptr on success
3380
 *         NULL on failure
3381
 */
3382
45.9k
cram_container *cram_new_container(int nrec, int nslice) {
3383
45.9k
    cram_container *c = calloc(1, sizeof(*c));
3384
45.9k
    enum cram_DS_ID id;
3385
3386
45.9k
    if (!c)
3387
0
        return NULL;
3388
3389
45.9k
    c->curr_ref = -2;
3390
3391
45.9k
    c->max_c_rec = nrec * nslice;
3392
45.9k
    c->curr_c_rec = 0;
3393
3394
45.9k
    c->max_rec = nrec;
3395
45.9k
    c->record_counter = 0;
3396
45.9k
    c->num_bases = 0;
3397
45.9k
    c->s_num_bases = 0;
3398
3399
45.9k
    c->max_slice = nslice;
3400
45.9k
    c->curr_slice = 0;
3401
3402
45.9k
    c->pos_sorted = 1;
3403
45.9k
    c->max_apos   = 0;
3404
45.9k
    c->multi_seq  = 0;
3405
45.9k
    c->qs_seq_orient = 1;
3406
45.9k
    c->no_ref = 0;
3407
45.9k
    c->embed_ref = -1; // automatic selection
3408
3409
45.9k
    c->bams = NULL;
3410
3411
45.9k
    if (!(c->slices = calloc(nslice != 0 ? nslice : 1, sizeof(cram_slice *))))
3412
0
        goto err;
3413
45.9k
    c->slice = NULL;
3414
3415
45.9k
    if (!(c->comp_hdr = cram_new_compression_header()))
3416
0
        goto err;
3417
45.9k
    c->comp_hdr_block = NULL;
3418
3419
1.33M
    for (id = DS_RN; id < DS_TN; id++)
3420
1.28M
        if (!(c->stats[id] = cram_stats_create())) goto err;
3421
3422
    //c->aux_B_stats = cram_stats_create();
3423
3424
45.9k
    if (!(c->tags_used = kh_init(m_tagmap)))
3425
0
        goto err;
3426
45.9k
    c->refs_used = 0;
3427
45.9k
    c->ref_free = 0;
3428
3429
45.9k
    return c;
3430
3431
0
 err:
3432
0
    if (c) {
3433
0
        if (c->slices)
3434
0
            free(c->slices);
3435
0
        free(c);
3436
0
    }
3437
0
    return NULL;
3438
45.9k
}
3439
3440
5.56k
static void free_bam_list(bam_seq_t *bams, int max_rec) {
3441
5.56k
    int i;
3442
55.6M
    for (i = 0; i < max_rec; i++)
3443
55.6M
        bam_free(&bams[i]);
3444
3445
5.56k
    free(bams);
3446
5.56k
}
3447
3448
66.2k
void cram_free_container(cram_container *c) {
3449
66.2k
    enum cram_DS_ID id;
3450
66.2k
    int i;
3451
3452
66.2k
    if (!c)
3453
0
        return;
3454
3455
66.2k
    if (c->refs_used)
3456
588
        free(c->refs_used);
3457
3458
66.2k
    if (c->landmark)
3459
49.1k
        free(c->landmark);
3460
3461
66.2k
    if (c->comp_hdr)
3462
46.7k
        cram_free_compression_header(c->comp_hdr);
3463
3464
66.2k
    if (c->comp_hdr_block)
3465
41.1k
        cram_free_block(c->comp_hdr_block);
3466
3467
    // Free the slices; filled out by encoder only
3468
66.2k
    if (c->slices) {
3469
81.6k
        for (i = 0; i < c->max_slice; i++) {
3470
35.6k
            if (c->slices[i])
3471
5.56k
                cram_free_slice(c->slices[i]);
3472
35.6k
            if (c->slices[i] == c->slice)
3473
35.6k
                c->slice = NULL;
3474
35.6k
        }
3475
45.9k
        free(c->slices);
3476
45.9k
    }
3477
3478
    // Free the current slice; set by both encoder & decoder
3479
66.2k
    if (c->slice) {
3480
0
        cram_free_slice(c->slice);
3481
0
        c->slice = NULL;
3482
0
    }
3483
3484
1.92M
    for (id = DS_RN; id < DS_TN; id++)
3485
1.85M
        if (c->stats[id]) cram_stats_free(c->stats[id]);
3486
3487
    //if (c->aux_B_stats) cram_stats_free(c->aux_B_stats);
3488
3489
66.2k
    if (c->tags_used) {
3490
45.9k
        khint_t k;
3491
3492
184k
        for (k = kh_begin(c->tags_used); k != kh_end(c->tags_used); k++) {
3493
138k
            if (!kh_exist(c->tags_used, k))
3494
76.9k
                continue;
3495
3496
61.1k
            cram_tag_map *tm = (cram_tag_map *)kh_val(c->tags_used, k);
3497
61.1k
            if (tm) {
3498
61.1k
                cram_codec *c = tm->codec;
3499
3500
61.1k
                if (c) c->free(c);
3501
3502
                // If tm->blk or tm->blk2 is set, then we haven't yet got to
3503
                // cram_encode_container which copies the blocks to s->aux_block
3504
                // and NULLifies tm->blk*.  In this case we failed to complete
3505
                // the container construction, so we have to free up our partially
3506
                // converted CRAM.
3507
61.1k
                cram_free_block(tm->blk);
3508
61.1k
                cram_free_block(tm->blk2);
3509
61.1k
                free(tm);
3510
61.1k
            }
3511
61.1k
        }
3512
3513
45.9k
        kh_destroy(m_tagmap, c->tags_used);
3514
45.9k
    }
3515
3516
66.2k
    if (c->ref_free)
3517
15.8k
        free(c->ref);
3518
3519
66.2k
    if (c->bams)
3520
815
        free_bam_list(c->bams, c->max_c_rec);
3521
3522
66.2k
    free(c);
3523
66.2k
}
3524
3525
/*
3526
 * Reads a container header.
3527
 *
3528
 * Returns cram_container on success
3529
 *         NULL on failure or no container left (fd->err == 0).
3530
 */
3531
20.6k
cram_container *cram_read_container(cram_fd *fd) {
3532
20.6k
    cram_container c2, *c;
3533
20.6k
    int i, s;
3534
20.6k
    size_t rd = 0;
3535
20.6k
    uint32_t crc = 0;
3536
3537
20.6k
    fd->err = 0;
3538
20.6k
    fd->eof = 0;
3539
3540
20.6k
    memset(&c2, 0, sizeof(c2));
3541
20.6k
    if (CRAM_MAJOR_VERS(fd->version) == 1) {
3542
11.0k
        if ((s = fd->vv.varint_decode32_crc(fd, &c2.length, &crc)) == -1) {
3543
45
            fd->eof = fd->empty_container ? 1 : 2;
3544
45
            return NULL;
3545
11.0k
        } else {
3546
11.0k
            rd+=s;
3547
11.0k
        }
3548
11.0k
    } else if (CRAM_MAJOR_VERS(fd->version) < 4) {
3549
4.51k
        uint32_t len;
3550
4.51k
        if ((s = int32_decode(fd, &c2.length)) == -1) {
3551
13
            if (CRAM_MAJOR_VERS(fd->version) == 2 &&
3552
9
                CRAM_MINOR_VERS(fd->version) == 0)
3553
4
                fd->eof = 1; // EOF blocks arrived in v2.1
3554
9
            else
3555
9
                fd->eof = fd->empty_container ? 1 : 2;
3556
13
            return NULL;
3557
4.50k
        } else {
3558
4.50k
            rd+=s;
3559
4.50k
        }
3560
4.50k
        len = le_int4(c2.length);
3561
4.50k
        crc = crc32(0L, (unsigned char *)&len, 4);
3562
4.50k
    }
3563
20.6k
    if ((s = fd->vv.varint_decode32s_crc(fd, &c2.ref_seq_id, &crc))   == -1) return NULL; else rd+=s;
3564
20.5k
    int32_t i32;
3565
20.5k
    if ((s = fd->vv.varint_decode32_crc(fd, &i32, &crc))== -1) return NULL; else rd+=s;
3566
20.5k
    c2.ref_seq_start = i32;
3567
20.5k
    if ((s = fd->vv.varint_decode32_crc(fd, &i32, &crc)) == -1) return NULL; else rd+=s;
3568
20.5k
    c2.ref_seq_span = i32;
3569
20.5k
    if ((s = fd->vv.varint_decode32_crc(fd, &c2.num_records, &crc))  == -1) return NULL; else rd+=s;
3570
3571
20.4k
    if (CRAM_MAJOR_VERS(fd->version) == 1) {
3572
10.9k
        c2.record_counter = 0;
3573
10.9k
        c2.num_bases = 0;
3574
10.9k
    } else {
3575
9.51k
        if (CRAM_MAJOR_VERS(fd->version) >= 3) {
3576
7.40k
            if ((s = fd->vv.varint_decode64_crc(fd, &c2.record_counter, &crc)) == -1)
3577
28
                return NULL;
3578
7.37k
            else
3579
7.37k
                rd += s;
3580
7.40k
        } else {
3581
2.11k
            int32_t i32;
3582
2.11k
            if ((s = fd->vv.varint_decode32_crc(fd, &i32, &crc)) == -1)
3583
10
                return NULL;
3584
2.10k
            else
3585
2.10k
                rd += s;
3586
2.10k
            c2.record_counter = i32;
3587
2.10k
        }
3588
3589
9.48k
        if ((s = fd->vv.varint_decode64_crc(fd, &c2.num_bases, &crc))== -1)
3590
57
            return NULL;
3591
9.42k
        else
3592
9.42k
            rd += s;
3593
9.48k
    }
3594
20.3k
    if ((s = fd->vv.varint_decode32_crc(fd, &c2.num_blocks, &crc))   == -1)
3595
31
        return NULL;
3596
20.3k
    else
3597
20.3k
        rd+=s;
3598
20.3k
    if ((s = fd->vv.varint_decode32_crc(fd, &c2.num_landmarks, &crc))== -1)
3599
35
        return NULL;
3600
20.3k
    else
3601
20.3k
        rd+=s;
3602
3603
20.3k
    if (c2.num_landmarks < 0 || c2.num_landmarks >= SIZE_MAX / sizeof(int32_t))
3604
74
        return NULL;
3605
3606
20.2k
    if (!(c = calloc(1, sizeof(*c))))
3607
0
        return NULL;
3608
3609
20.2k
    *c = c2;
3610
20.2k
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
3611
20.2k
    if (c->num_landmarks > FUZZ_ALLOC_LIMIT/sizeof(int32_t)) {
3612
8
        fd->err = errno = ENOMEM;
3613
8
        cram_free_container(c);
3614
8
        return NULL;
3615
8
    }
3616
20.2k
#endif
3617
    // We already have an upper limit of 10,000 blocks per slice to prevent
3618
    // bad data using excessive memory.  We could in theory have many slices
3619
    // per container, but in practice we only ever stick to 1 in modern
3620
    // implementations.  Nonetheless, let's use a limit here too on
3621
    // landmarks (which are offsets relative to this container position).
3622
20.2k
    if (c->num_landmarks > 1000000) {
3623
69
        cram_free_container(c);
3624
69
        return NULL;
3625
69
    }
3626
20.1k
    if (c->num_landmarks && !(c->landmark = hts_malloc_p(sizeof(*c->landmark), c->num_landmarks))) {
3627
0
        fd->err = errno;
3628
0
        cram_free_container(c);
3629
0
        return NULL;
3630
0
    }
3631
313k
    for (i = 0; i < c->num_landmarks; i++) {
3632
293k
        if ((s = fd->vv.varint_decode32_crc(fd, &c->landmark[i], &crc)) == -1) {
3633
233
            cram_free_container(c);
3634
233
            return NULL;
3635
292k
        } else {
3636
292k
            rd += s;
3637
292k
        }
3638
293k
    }
3639
3640
19.9k
    if (CRAM_MAJOR_VERS(fd->version) >= 3) {
3641
7.23k
        if (-1 == int32_decode(fd, (int32_t *)&c->crc32)) {
3642
16
            cram_free_container(c);
3643
16
            return NULL;
3644
7.21k
        } else {
3645
7.21k
            rd+=4;
3646
7.21k
        }
3647
3648
7.21k
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
3649
        // Pretend the CRC was OK so the fuzzer doesn't have to get it right
3650
7.21k
        crc = c->crc32;
3651
7.21k
#endif
3652
3653
7.21k
        if (crc != c->crc32) {
3654
0
            hts_log_error("Container header CRC32 failure");
3655
0
            cram_free_container(c);
3656
0
            return NULL;
3657
0
        }
3658
7.21k
    }
3659
3660
19.9k
    c->offset = rd;
3661
19.9k
    c->slices = NULL;
3662
19.9k
    c->slice = NULL;
3663
19.9k
    c->curr_slice = 0;
3664
19.9k
    c->max_slice = c->num_landmarks;
3665
19.9k
    c->slice_rec = 0;
3666
19.9k
    c->curr_rec = 0;
3667
19.9k
    c->max_rec = 0;
3668
3669
19.9k
    if (c->ref_seq_id == -2) {
3670
17
        c->multi_seq = 1;
3671
17
        fd->multi_seq = 1;
3672
17
    }
3673
3674
19.9k
    fd->empty_container =
3675
19.9k
        (c->num_records == 0 &&
3676
10.1k
         c->ref_seq_id == -1 &&
3677
19.9k
         c->ref_seq_start == 0x454f46 /* EOF */) ? 1 : 0;
3678
3679
19.9k
    return c;
3680
19.9k
}
3681
3682
3683
/* MAXIMUM storage size needed for the container. */
3684
0
int cram_container_size(cram_container *c) {
3685
0
    return 55 + 5*c->num_landmarks;
3686
0
}
3687
3688
3689
/*
3690
 * Stores the container structure in dat and returns *size as the
3691
 * number of bytes written to dat[].  The input size of dat is also
3692
 * held in *size and should be initialised to cram_container_size(c).
3693
 *
3694
 * Returns 0 on success;
3695
 *        -1 on failure
3696
 */
3697
int cram_store_container(cram_fd *fd, cram_container *c, char *dat, int *size)
3698
0
{
3699
0
    char *cp = (char *)dat;
3700
0
    int i;
3701
3702
    // Check the input buffer is large enough according to our stated
3703
    // requirements. (NOTE: it may actually take less.)
3704
0
    if (cram_container_size(c) > *size)
3705
0
        return -1;
3706
3707
0
    if (CRAM_MAJOR_VERS(fd->version) == 1) {
3708
0
        cp += itf8_put(cp, c->length);
3709
0
    } else {
3710
0
        *(int32_t *)cp = le_int4(c->length);
3711
0
        cp += 4;
3712
0
    }
3713
0
    if (c->multi_seq) {
3714
0
        cp += fd->vv.varint_put32(cp, NULL, -2);
3715
0
        cp += fd->vv.varint_put32(cp, NULL, 0);
3716
0
        cp += fd->vv.varint_put32(cp, NULL, 0);
3717
0
    } else {
3718
0
        cp += fd->vv.varint_put32s(cp, NULL, c->ref_seq_id);
3719
0
        cp += fd->vv.varint_put32(cp, NULL, c->ref_seq_start);
3720
0
        cp += fd->vv.varint_put32(cp, NULL, c->ref_seq_span);
3721
0
    }
3722
0
    cp += fd->vv.varint_put32(cp, NULL, c->num_records);
3723
0
    if (CRAM_MAJOR_VERS(fd->version) == 2) {
3724
0
        cp += fd->vv.varint_put64(cp, NULL, c->record_counter);
3725
0
    } else if (CRAM_MAJOR_VERS(fd->version) >= 3) {
3726
0
        cp += fd->vv.varint_put32(cp, NULL, c->record_counter);
3727
0
    }
3728
0
    cp += fd->vv.varint_put64(cp, NULL, c->num_bases);
3729
0
    cp += fd->vv.varint_put32(cp, NULL, c->num_blocks);
3730
0
    cp += fd->vv.varint_put32(cp, NULL, c->num_landmarks);
3731
0
    for (i = 0; i < c->num_landmarks; i++)
3732
0
        cp += fd->vv.varint_put32(cp, NULL, c->landmark[i]);
3733
3734
0
    if (CRAM_MAJOR_VERS(fd->version) >= 3) {
3735
0
        c->crc32 = crc32(0L, (uc *)dat, cp-dat);
3736
0
        cp[0] =  c->crc32        & 0xff;
3737
0
        cp[1] = (c->crc32 >>  8) & 0xff;
3738
0
        cp[2] = (c->crc32 >> 16) & 0xff;
3739
0
        cp[3] = (c->crc32 >> 24) & 0xff;
3740
0
        cp += 4;
3741
0
    }
3742
3743
0
    *size = cp-dat; // actual used size
3744
3745
0
    return 0;
3746
0
}
3747
3748
3749
/*
3750
 * Writes a container structure.
3751
 *
3752
 * Returns 0 on success
3753
 *        -1 on failure
3754
 */
3755
54.9k
int cram_write_container(cram_fd *fd, cram_container *c) {
3756
54.9k
    char buf_a[1024], *buf = buf_a, *cp;
3757
54.9k
    int i;
3758
3759
54.9k
    if (61 + c->num_landmarks * 10 >= 1024) {
3760
0
        buf = malloc(61 + c->num_landmarks * 10);
3761
0
        if (!buf)
3762
0
            return -1;
3763
0
    }
3764
54.9k
    cp = buf;
3765
3766
54.9k
    if (CRAM_MAJOR_VERS(fd->version) == 1) {
3767
0
        cp += itf8_put(cp, c->length);
3768
54.9k
    } else if (CRAM_MAJOR_VERS(fd->version) <= 3) {
3769
54.9k
        *(int32_t *)cp = le_int4(c->length);
3770
54.9k
        cp += 4;
3771
54.9k
    } else {
3772
0
        cp += fd->vv.varint_put32(cp, NULL, c->length);
3773
0
    }
3774
54.9k
    if (c->multi_seq) {
3775
576
        cp += fd->vv.varint_put32(cp, NULL, (uint32_t)-2);
3776
576
        cp += fd->vv.varint_put32(cp, NULL, 0);
3777
576
        cp += fd->vv.varint_put32(cp, NULL, 0);
3778
54.3k
    } else {
3779
54.3k
        cp += fd->vv.varint_put32s(cp, NULL, c->ref_seq_id);
3780
54.3k
        cp += fd->vv.varint_put32(cp, NULL, c->ref_seq_start);
3781
54.3k
        cp += fd->vv.varint_put32(cp, NULL, c->ref_seq_span);
3782
54.3k
    }
3783
54.9k
    cp += fd->vv.varint_put32(cp, NULL, c->num_records);
3784
54.9k
    if (CRAM_MAJOR_VERS(fd->version) >= 3)
3785
54.9k
        cp += fd->vv.varint_put64(cp, NULL, c->record_counter);
3786
0
    else
3787
0
        cp += fd->vv.varint_put32(cp, NULL, c->record_counter);
3788
54.9k
    cp += fd->vv.varint_put64(cp, NULL, c->num_bases);
3789
54.9k
    cp += fd->vv.varint_put32(cp, NULL, c->num_blocks);
3790
54.9k
    cp += fd->vv.varint_put32(cp, NULL, c->num_landmarks);
3791
110k
    for (i = 0; i < c->num_landmarks; i++)
3792
55.1k
        cp += fd->vv.varint_put32(cp, NULL, c->landmark[i]);
3793
3794
54.9k
    if (CRAM_MAJOR_VERS(fd->version) >= 3) {
3795
54.9k
        c->crc32 = crc32(0L, (uc *)buf, cp-buf);
3796
54.9k
        cp[0] =  c->crc32        & 0xff;
3797
54.9k
        cp[1] = (c->crc32 >>  8) & 0xff;
3798
54.9k
        cp[2] = (c->crc32 >> 16) & 0xff;
3799
54.9k
        cp[3] = (c->crc32 >> 24) & 0xff;
3800
54.9k
        cp += 4;
3801
54.9k
    }
3802
3803
54.9k
    if (cp-buf != hwrite(fd->fp, buf, cp-buf)) {
3804
0
        if (buf != buf_a)
3805
0
            free(buf);
3806
0
        return -1;
3807
0
    }
3808
3809
54.9k
    if (buf != buf_a)
3810
0
        free(buf);
3811
3812
54.9k
    return 0;
3813
54.9k
}
3814
3815
// common component shared by cram_flush_container{,_mt}
3816
34.5k
static int cram_flush_container2(cram_fd *fd, cram_container *c) {
3817
34.5k
    int i, j;
3818
3819
34.5k
    if (c->curr_slice > 0 && !c->slices)
3820
0
        return -1;
3821
3822
    //fprintf(stderr, "Writing container %d, sum %u\n", c->record_counter, sum);
3823
3824
34.5k
    off_t c_offset = htell(fd->fp); // File offset of container
3825
3826
    /* Write the container struct itself */
3827
34.5k
    if (0 != cram_write_container(fd, c))
3828
0
        return -1;
3829
3830
34.5k
    off_t hdr_size = htell(fd->fp) - c_offset;
3831
3832
    /* And the compression header */
3833
34.5k
    if (0 != cram_write_block(fd, c->comp_hdr_block))
3834
0
        return -1;
3835
3836
    /* Followed by the slice blocks */
3837
34.5k
    off_t file_offset = htell(fd->fp);
3838
69.1k
    for (i = 0; i < c->curr_slice; i++) {
3839
34.5k
        cram_slice *s = c->slices[i];
3840
34.5k
        off_t spos = file_offset - c_offset - hdr_size;
3841
3842
34.5k
        if (0 != cram_write_block(fd, s->hdr_block))
3843
0
            return -1;
3844
3845
237k
        for (j = 0; j < s->hdr->num_blocks; j++) {
3846
203k
            if (0 != cram_write_block(fd, s->block[j]))
3847
0
                return -1;
3848
203k
        }
3849
3850
34.5k
        file_offset = htell(fd->fp);
3851
34.5k
        off_t sz = file_offset - c_offset - hdr_size - spos;
3852
3853
34.5k
        if (fd->idxfp) {
3854
0
            if (cram_index_slice(fd, c, s, fd->idxfp, c_offset, spos, sz) < 0)
3855
0
                return -1;
3856
0
        }
3857
34.5k
    }
3858
3859
34.5k
    return 0;
3860
34.5k
}
3861
3862
/*
3863
 * Flushes a completely or partially full container to disk, writing
3864
 * container structure, header and blocks. This also calls the encoder
3865
 * functions.
3866
 *
3867
 * Returns 0 on success
3868
 *        -1 on failure
3869
 */
3870
35.6k
int cram_flush_container(cram_fd *fd, cram_container *c) {
3871
    /* Encode the container blocks and generate compression header */
3872
35.6k
    if (0 != cram_encode_container(fd, c))
3873
1.10k
        return -1;
3874
3875
34.5k
    return cram_flush_container2(fd, c);
3876
35.6k
}
3877
3878
typedef struct {
3879
    cram_fd *fd;
3880
    cram_container *c;
3881
} cram_job;
3882
3883
0
void *cram_flush_thread(void *arg) {
3884
0
    cram_job *j = (cram_job *)arg;
3885
3886
    /* Encode the container blocks and generate compression header */
3887
0
    if (0 != cram_encode_container(j->fd, j->c)) {
3888
0
        hts_log_error("Call to cram_encode_container failed");
3889
0
        return NULL;
3890
0
    }
3891
3892
0
    return arg;
3893
0
}
3894
3895
0
static int cram_flush_result(cram_fd *fd) {
3896
0
    int i, ret = 0;
3897
0
    hts_tpool_result *r;
3898
0
    cram_container *lc = NULL;
3899
3900
    // NB: we can have one result per slice, not per container,
3901
    // so we need to free the container only after all slices
3902
    // within it have been freed.  (Automatic via reference counting.)
3903
0
    while ((r = hts_tpool_next_result(fd->rqueue))) {
3904
0
        cram_job *j = (cram_job *)hts_tpool_result_data(r);
3905
0
        cram_container *c;
3906
3907
0
        if (!j) {
3908
0
            hts_tpool_delete_result(r, 0);
3909
0
            return -1;
3910
0
        }
3911
3912
0
        fd = j->fd;
3913
0
        c = j->c;
3914
3915
0
        if (fd->mode == 'w')
3916
0
            if (0 != cram_flush_container2(fd, c))
3917
0
                return -1;
3918
3919
        // Free the slices; filled out by encoder only
3920
0
        if (c->slices) {
3921
0
            for (i = 0; i < c->max_slice; i++) {
3922
0
                if (c->slices[i])
3923
0
                    cram_free_slice(c->slices[i]);
3924
0
                if (c->slices[i] == c->slice)
3925
0
                    c->slice = NULL;
3926
0
                c->slices[i] = NULL;
3927
0
            }
3928
0
        }
3929
3930
        // Free the current slice; set by both encoder & decoder
3931
0
        if (c->slice) {
3932
0
            cram_free_slice(c->slice);
3933
0
            c->slice = NULL;
3934
0
        }
3935
0
        c->curr_slice = 0;
3936
3937
        // Our jobs will be in order, so we free the last
3938
        // container when our job has switched to a new one.
3939
0
        if (c != lc) {
3940
0
            if (lc) {
3941
0
                if (fd->ctr == lc)
3942
0
                    fd->ctr = NULL;
3943
0
                if (fd->ctr_mt == lc)
3944
0
                    fd->ctr_mt = NULL;
3945
0
                cram_free_container(lc);
3946
0
            }
3947
0
            lc = c;
3948
0
        }
3949
3950
0
        hts_tpool_delete_result(r, 1);
3951
0
    }
3952
0
    if (lc) {
3953
0
        if (fd->ctr == lc)
3954
0
            fd->ctr = NULL;
3955
0
        if (fd->ctr_mt == lc)
3956
0
            fd->ctr_mt = NULL;
3957
0
        cram_free_container(lc);
3958
0
    }
3959
3960
0
    return ret;
3961
0
}
3962
3963
// Note: called while metrics_lock is held.
3964
// Will be left in this state too, but may temporarily unlock.
3965
3.56k
void reset_metrics(cram_fd *fd) {
3966
3.56k
    int i;
3967
3968
3.56k
    if (fd->pool) {
3969
        // If multi-threaded we have multiple blocks being
3970
        // compressed already and several on the to-do list
3971
        // (fd->rqueue->pending).  It's tricky to reset the
3972
        // metrics exactly the correct point, so instead we
3973
        // just flush the pool, reset, and then continue again.
3974
3975
        // Don't bother starting a new trial before then though.
3976
0
        for (i = 0; i < DS_END; i++) {
3977
0
            cram_metrics *m = fd->m[i];
3978
0
            if (!m)
3979
0
                continue;
3980
0
            m->next_trial = 999;
3981
0
        }
3982
3983
0
        pthread_mutex_unlock(&fd->metrics_lock);
3984
0
        hts_tpool_process_flush(fd->rqueue);
3985
0
        pthread_mutex_lock(&fd->metrics_lock);
3986
0
    }
3987
3988
171k
    for (i = 0; i < DS_END; i++) {
3989
167k
        cram_metrics *m = fd->m[i];
3990
167k
        if (!m)
3991
0
            continue;
3992
3993
167k
        m->trial = NTRIALS;
3994
167k
        m->next_trial = TRIAL_SPAN;
3995
167k
        m->revised_method = 0;
3996
167k
        m->unpackable = 0;
3997
3998
167k
        memset(m->sz, 0, sizeof(m->sz));
3999
167k
    }
4000
3.56k
}
4001
4002
35.6k
int cram_flush_container_mt(cram_fd *fd, cram_container *c) {
4003
35.6k
    cram_job *j;
4004
4005
    // At the junction of mapped to unmapped data the compression
4006
    // methods may need to change due to very different statistical
4007
    // properties; particularly BA if minhash sorted.
4008
    //
4009
    // However with threading we'll have several in-flight blocks
4010
    // arriving out of order.
4011
    //
4012
    // So we do one trial reset of NThreads to last for NThreads
4013
    // duration to get us over this transition period, followed
4014
    // by another retrial of the usual ntrials & trial span.
4015
35.6k
    pthread_mutex_lock(&fd->metrics_lock);
4016
35.6k
    if (c->n_mapped < 0.3*c->curr_rec &&
4017
20.0k
        fd->last_mapped > 0.7*c->max_rec) {
4018
3.56k
        reset_metrics(fd);
4019
3.56k
    }
4020
35.6k
    fd->last_mapped = c->n_mapped * (c->max_rec+1)/(c->curr_rec+1) ;
4021
35.6k
    pthread_mutex_unlock(&fd->metrics_lock);
4022
4023
35.6k
    if (!fd->pool)
4024
35.6k
        return cram_flush_container(fd, c);
4025
4026
0
    if (!(j = malloc(sizeof(*j))))
4027
0
        return -1;
4028
0
    j->fd = fd;
4029
0
    j->c = c;
4030
4031
    // Flush the job.  Note our encoder queue may be full, so we
4032
    // either have to keep trying in non-blocking mode (what we do) or
4033
    // use a dedicated separate thread for draining the queue.
4034
0
    for (;;) {
4035
0
        errno = 0;
4036
0
        hts_tpool_dispatch2(fd->pool, fd->rqueue, cram_flush_thread, j, 1);
4037
0
        int pending = (errno == EAGAIN);
4038
0
        if (cram_flush_result(fd) != 0)
4039
0
            return -1;
4040
0
        if (!pending)
4041
0
            break;
4042
4043
0
        hts_usleep(1000);
4044
0
    }
4045
4046
0
    return 0;
4047
0
}
4048
4049
/* ----------------------------------------------------------------------
4050
 * Compression headers; the first part of the container
4051
 */
4052
4053
/*
4054
 * Creates a new blank container compression header
4055
 *
4056
 * Returns header ptr on success
4057
 *         NULL on failure
4058
 */
4059
45.9k
cram_block_compression_hdr *cram_new_compression_header(void) {
4060
45.9k
    cram_block_compression_hdr *hdr = calloc(1, sizeof(*hdr));
4061
45.9k
    if (!hdr)
4062
0
        return NULL;
4063
4064
45.9k
    if (!(hdr->TD_blk = cram_new_block(CORE, 0))) {
4065
0
        free(hdr);
4066
0
        return NULL;
4067
0
    }
4068
4069
45.9k
    if (!(hdr->TD_hash = kh_init(m_s2i))) {
4070
0
        cram_free_block(hdr->TD_blk);
4071
0
        free(hdr);
4072
0
        return NULL;
4073
0
    }
4074
4075
45.9k
    if (!(hdr->TD_keys = string_pool_create(8192))) {
4076
0
        kh_destroy(m_s2i, hdr->TD_hash);
4077
0
        cram_free_block(hdr->TD_blk);
4078
0
        free(hdr);
4079
0
        return NULL;
4080
0
    }
4081
4082
45.9k
    return hdr;
4083
45.9k
}
4084
4085
48.2k
void cram_free_compression_header(cram_block_compression_hdr *hdr) {
4086
48.2k
    int i;
4087
4088
48.2k
    if (hdr->landmark)
4089
2.27k
        free(hdr->landmark);
4090
4091
48.2k
    if (hdr->preservation_map)
4092
36.8k
        kh_destroy(map, hdr->preservation_map);
4093
4094
1.59M
    for (i = 0; i < CRAM_MAP_HASH; i++) {
4095
1.54M
        cram_map *m, *m2;
4096
1.57M
        for (m = hdr->rec_encoding_map[i]; m; m = m2) {
4097
32.9k
            m2 = m->next;
4098
32.9k
            if (m->codec)
4099
0
                m->codec->free(m->codec);
4100
32.9k
            free(m);
4101
32.9k
        }
4102
1.54M
    }
4103
4104
1.59M
    for (i = 0; i < CRAM_MAP_HASH; i++) {
4105
1.54M
        cram_map *m, *m2;
4106
1.54M
        for (m = hdr->tag_encoding_map[i]; m; m = m2) {
4107
1.42k
            m2 = m->next;
4108
1.42k
            if (m->codec)
4109
1.42k
                m->codec->free(m->codec);
4110
1.42k
            free(m);
4111
1.42k
        }
4112
1.54M
    }
4113
4114
2.31M
    for (i = 0; i < DS_END; i++) {
4115
2.26M
        if (hdr->codecs[i])
4116
659k
            hdr->codecs[i]->free(hdr->codecs[i]);
4117
2.26M
    }
4118
4119
48.2k
    if (hdr->TL)
4120
48
        free(hdr->TL);
4121
48.2k
    if (hdr->TD_blk)
4122
46.0k
        cram_free_block(hdr->TD_blk);
4123
48.2k
    if (hdr->TD_hash)
4124
45.9k
        kh_destroy(m_s2i, hdr->TD_hash);
4125
48.2k
    if (hdr->TD_keys)
4126
45.9k
        string_pool_destroy(hdr->TD_keys);
4127
4128
48.2k
    free(hdr);
4129
48.2k
}
4130
4131
4132
/* ----------------------------------------------------------------------
4133
 * Slices and slice headers
4134
 */
4135
4136
35.8k
void cram_free_slice_header(cram_block_slice_hdr *hdr) {
4137
35.8k
    if (!hdr)
4138
0
        return;
4139
4140
35.8k
    if (hdr->block_content_ids)
4141
34.9k
        free(hdr->block_content_ids);
4142
4143
35.8k
    free(hdr);
4144
4145
35.8k
    return;
4146
35.8k
}
4147
4148
35.9k
void cram_free_slice(cram_slice *s) {
4149
35.9k
    if (!s)
4150
0
        return;
4151
4152
35.9k
    if (s->bl) {
4153
0
        free_bam_list(s->bl->bams, s->bl->nbams);
4154
0
        free(s->bl);
4155
0
    }
4156
4157
35.9k
    if (s->hdr_block)
4158
34.7k
        cram_free_block(s->hdr_block);
4159
4160
35.9k
    if (s->block) {
4161
34.9k
        int i;
4162
4163
34.9k
        if (s->hdr) {
4164
313k
            for (i = 0; i < s->hdr->num_blocks; i++) {
4165
278k
                if (i > 0 && s->block[i] == s->block[0])
4166
42.8k
                    continue;
4167
235k
                cram_free_block(s->block[i]);
4168
235k
            }
4169
34.9k
        }
4170
34.9k
        free(s->block);
4171
34.9k
    }
4172
4173
35.9k
    {
4174
        // Normally already copied into s->block[], but potentially still
4175
        // here if we error part way through cram_encode_slice.
4176
35.9k
        int i;
4177
95.9k
        for (i = 0; i < s->naux_block; i++)
4178
59.9k
            cram_free_block(s->aux_block[i]);
4179
35.9k
    }
4180
4181
35.9k
    if (s->block_by_id)
4182
114
        free(s->block_by_id);
4183
4184
35.9k
    if (s->hdr)
4185
35.8k
        cram_free_slice_header(s->hdr);
4186
4187
35.9k
    if (s->seqs_blk)
4188
35.8k
        cram_free_block(s->seqs_blk);
4189
4190
35.9k
    if (s->qual_blk)
4191
1.03k
        cram_free_block(s->qual_blk);
4192
4193
35.9k
    if (s->name_blk)
4194
1.03k
        cram_free_block(s->name_blk);
4195
4196
35.9k
    if (s->aux_blk)
4197
35.8k
        cram_free_block(s->aux_blk);
4198
4199
35.9k
    if (s->base_blk)
4200
1.03k
        cram_free_block(s->base_blk);
4201
4202
35.9k
    if (s->soft_blk)
4203
1.03k
        cram_free_block(s->soft_blk);
4204
4205
35.9k
    if (s->cigar)
4206
35.8k
        free(s->cigar);
4207
4208
35.9k
    if (s->crecs)
4209
35.7k
        free(s->crecs);
4210
4211
35.9k
    if (s->features)
4212
15.1k
        free(s->features);
4213
4214
35.9k
    if (s->TN)
4215
0
        free(s->TN);
4216
4217
35.9k
    if (s->pair_keys)
4218
35.6k
        string_pool_destroy(s->pair_keys);
4219
4220
35.9k
    if (s->pair[0])
4221
35.6k
        kh_destroy(m_s2i, s->pair[0]);
4222
35.9k
    if (s->pair[1])
4223
35.6k
        kh_destroy(m_s2i, s->pair[1]);
4224
4225
35.9k
    if (s->aux_block)
4226
30.5k
        free(s->aux_block);
4227
4228
35.9k
    free(s);
4229
35.9k
}
4230
4231
/*
4232
 * Creates a new empty slice in memory, for subsequent writing to
4233
 * disk.
4234
 *
4235
 * Returns cram_slice ptr on success
4236
 *         NULL on failure
4237
 */
4238
35.6k
cram_slice *cram_new_slice(enum cram_content_type type, int nrecs) {
4239
35.6k
    cram_slice *s = calloc(1, sizeof(*s));
4240
35.6k
    if (!s)
4241
0
        return NULL;
4242
4243
35.6k
    if (!(s->hdr = (cram_block_slice_hdr *)calloc(1, sizeof(*s->hdr))))
4244
0
        goto err;
4245
35.6k
    s->hdr->content_type = type;
4246
4247
35.6k
    s->hdr_block = NULL;
4248
35.6k
    s->block = NULL;
4249
35.6k
    s->block_by_id = NULL;
4250
35.6k
    s->last_apos = 0;
4251
35.6k
    if (!(s->crecs = hts_malloc_p(sizeof(*s->crecs), nrecs)))  goto err;
4252
35.6k
    s->cigar_alloc = 1024;
4253
35.6k
    if (!(s->cigar = hts_malloc_p(sizeof(*s->cigar), s->cigar_alloc))) goto err;
4254
35.6k
    s->ncigar = 0;
4255
4256
35.6k
    if (!(s->seqs_blk = cram_new_block(EXTERNAL, 0)))       goto err;
4257
35.6k
    if (!(s->qual_blk = cram_new_block(EXTERNAL, DS_QS)))   goto err;
4258
35.6k
    if (!(s->name_blk = cram_new_block(EXTERNAL, DS_RN)))   goto err;
4259
35.6k
    if (!(s->aux_blk  = cram_new_block(EXTERNAL, DS_aux)))  goto err;
4260
35.6k
    if (!(s->base_blk = cram_new_block(EXTERNAL, DS_IN)))   goto err;
4261
35.6k
    if (!(s->soft_blk = cram_new_block(EXTERNAL, DS_SC)))   goto err;
4262
4263
35.6k
    s->features = NULL;
4264
35.6k
    s->nfeatures = s->afeatures = 0;
4265
4266
35.6k
#ifndef TN_external
4267
35.6k
    s->TN = NULL;
4268
35.6k
    s->nTN = s->aTN = 0;
4269
35.6k
#endif
4270
4271
    // Volatile keys as we do realloc in dstring
4272
35.6k
    if (!(s->pair_keys = string_pool_create(8192))) goto err;
4273
35.6k
    if (!(s->pair[0] = kh_init(m_s2i)))             goto err;
4274
35.6k
    if (!(s->pair[1] = kh_init(m_s2i)))             goto err;
4275
4276
#ifdef BA_external
4277
    s->BA_len = 0;
4278
#endif
4279
4280
35.6k
    return s;
4281
4282
0
 err:
4283
0
    if (s)
4284
0
        cram_free_slice(s);
4285
4286
0
    return NULL;
4287
35.6k
}
4288
4289
/*
4290
 * Loads an entire slice.
4291
 * FIXME: In 1.0 the native unit of slices within CRAM is broken
4292
 * as slices contain references to objects in other slices.
4293
 * To work around this while keeping the slice oriented outer loop
4294
 * we read all slices and stitch them together into a fake large
4295
 * slice instead.
4296
 *
4297
 * Returns cram_slice ptr on success
4298
 *         NULL on failure
4299
 */
4300
288
cram_slice *cram_read_slice(cram_fd *fd) {
4301
288
    cram_block *b = cram_read_block(fd);
4302
288
    cram_slice *s = calloc(1, sizeof(*s));
4303
288
    int i, n, max_id, min_id;
4304
4305
288
    if (!b || !s)
4306
9
        goto err;
4307
4308
279
    s->hdr_block = b;
4309
279
    switch (b->content_type) {
4310
243
    case MAPPED_SLICE:
4311
273
    case UNMAPPED_SLICE:
4312
273
        if (!(s->hdr = cram_decode_slice_header(fd, b)))
4313
81
            goto err;
4314
192
        break;
4315
4316
192
    default:
4317
6
        hts_log_error("Unexpected block of type %s",
4318
6
                      cram_content_type2str(b->content_type));
4319
6
        goto err;
4320
279
    }
4321
4322
192
    if (s->hdr->num_blocks < 1) {
4323
0
        hts_log_error("Slice does not include any data blocks");
4324
0
        goto err;
4325
0
    }
4326
4327
192
    s->block = calloc(n = s->hdr->num_blocks, sizeof(*s->block));
4328
192
    if (!s->block)
4329
0
        goto err;
4330
4331
1.16k
    for (max_id = i = 0, min_id = INT_MAX; i < n; i++) {
4332
1.04k
        if (!(s->block[i] = cram_read_block(fd)))
4333
78
            goto err;
4334
4335
969
        if (s->block[i]->content_type == EXTERNAL) {
4336
141
            if (max_id < s->block[i]->content_id)
4337
60
                max_id = s->block[i]->content_id;
4338
141
            if (min_id > s->block[i]->content_id)
4339
84
                min_id = s->block[i]->content_id;
4340
141
        }
4341
969
    }
4342
4343
114
    if (!(s->block_by_id = calloc(512, sizeof(s->block[0]))))
4344
0
        goto err;
4345
4346
921
    for (i = 0; i < n; i++) {
4347
807
        if (s->block[i]->content_type != EXTERNAL)
4348
696
            continue;
4349
111
        uint32_t v = s->block[i]->content_id;
4350
111
        if (v >= 256)
4351
24
            v = 256 + v % 251;
4352
111
        s->block_by_id[v] = s->block[i];
4353
111
    }
4354
4355
    /* Initialise encoding/decoding tables */
4356
114
    s->cigar_alloc = 1024;
4357
114
    if (!(s->cigar = hts_malloc_p(sizeof(*s->cigar), s->cigar_alloc))) goto err;
4358
114
    s->ncigar = 0;
4359
4360
114
    if (!(s->seqs_blk = cram_new_block(EXTERNAL, 0)))      goto err;
4361
114
    if (!(s->qual_blk = cram_new_block(EXTERNAL, DS_QS)))  goto err;
4362
114
    if (!(s->name_blk = cram_new_block(EXTERNAL, DS_RN)))  goto err;
4363
114
    if (!(s->aux_blk  = cram_new_block(EXTERNAL, DS_aux))) goto err;
4364
114
    if (!(s->base_blk = cram_new_block(EXTERNAL, DS_IN)))  goto err;
4365
114
    if (!(s->soft_blk = cram_new_block(EXTERNAL, DS_SC)))  goto err;
4366
4367
114
    s->crecs = NULL;
4368
4369
114
    s->last_apos = s->hdr->ref_seq_start;
4370
114
    s->decode_md = fd->decode_md;
4371
4372
114
    return s;
4373
4374
174
 err:
4375
174
    if (b)
4376
165
        cram_free_block(b);
4377
174
    if (s) {
4378
174
        s->hdr_block = NULL;
4379
174
        cram_free_slice(s);
4380
174
    }
4381
174
    return NULL;
4382
114
}
4383
4384
4385
/* ----------------------------------------------------------------------
4386
 * CRAM file definition (header)
4387
 */
4388
4389
/*
4390
 * Reads a CRAM file definition structure.
4391
 * Returns file_def ptr on success
4392
 *         NULL on failure
4393
 */
4394
11.3k
cram_file_def *cram_read_file_def(cram_fd *fd) {
4395
11.3k
    cram_file_def *def = malloc(sizeof(*def));
4396
11.3k
    if (!def)
4397
0
        return NULL;
4398
4399
11.3k
    if (26 != hread(fd->fp, &def->magic[0], 26)) {
4400
7
        free(def);
4401
7
        return NULL;
4402
7
    }
4403
4404
11.3k
    if (memcmp(def->magic, "CRAM", 4) != 0) {
4405
1
        free(def);
4406
1
        return NULL;
4407
1
    }
4408
4409
11.3k
    if (def->major_version > 4) {
4410
1
        hts_log_error("CRAM version number mismatch. Expected 1.x, 2.x, 3.x or 4.x, got %d.%d",
4411
1
                      def->major_version, def->minor_version);
4412
1
        free(def);
4413
1
        return NULL;
4414
1
    }
4415
4416
11.3k
    fd->first_container += 26;
4417
11.3k
    fd->curr_position = fd->first_container;
4418
11.3k
    fd->last_slice = 0;
4419
4420
11.3k
    return def;
4421
11.3k
}
4422
4423
/*
4424
 * Writes a cram_file_def structure to cram_fd.
4425
 * Returns 0 on success
4426
 *        -1 on failure
4427
 */
4428
10.2k
int cram_write_file_def(cram_fd *fd, cram_file_def *def) {
4429
10.2k
    return (hwrite(fd->fp, &def->magic[0], 26) == 26) ? 0 : -1;
4430
10.2k
}
4431
4432
22.3k
void cram_free_file_def(cram_file_def *def) {
4433
22.3k
    if (def) free(def);
4434
22.3k
}
4435
4436
/* ----------------------------------------------------------------------
4437
 * SAM header I/O
4438
 */
4439
4440
4441
/*
4442
 * Reads the SAM header from the first CRAM data block.
4443
 * Also performs minimal parsing to extract read-group
4444
 * and sample information.
4445
4446
 * Returns SAM hdr ptr on success
4447
 *         NULL on failure
4448
 */
4449
11.3k
sam_hdr_t *cram_read_SAM_hdr(cram_fd *fd) {
4450
11.3k
    int32_t header_len;
4451
11.3k
    char *header;
4452
11.3k
    sam_hdr_t *hdr;
4453
4454
    /* 1.1 onwards stores the header in the first block of a container */
4455
11.3k
    if (CRAM_MAJOR_VERS(fd->version) == 1) {
4456
        /* Length */
4457
9.30k
        if (-1 == int32_decode(fd, &header_len))
4458
2
            return NULL;
4459
4460
9.29k
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
4461
9.29k
        if (header_len > FUZZ_ALLOC_LIMIT)
4462
2
            return NULL;
4463
9.29k
#endif
4464
4465
        /* Alloc and read */
4466
9.29k
        if (header_len < 0 || NULL == (header = malloc((size_t) header_len+1)))
4467
0
            return NULL;
4468
4469
9.29k
        if (header_len != hread(fd->fp, header, header_len)) {
4470
28
            free(header);
4471
28
            return NULL;
4472
28
        }
4473
9.26k
        header[header_len] = '\0';
4474
4475
9.26k
        fd->first_container += 4 + header_len;
4476
9.26k
    } else {
4477
2.00k
        cram_container *c = cram_read_container(fd);
4478
2.00k
        cram_block *b;
4479
2.00k
        int i;
4480
2.00k
        int64_t len;
4481
4482
2.00k
        if (!c)
4483
109
            return NULL;
4484
4485
1.89k
        fd->first_container += c->length + c->offset;
4486
1.89k
        fd->curr_position = fd->first_container;
4487
4488
1.89k
        if (c->num_blocks < 1) {
4489
41
            cram_free_container(c);
4490
41
            return NULL;
4491
41
        }
4492
4493
1.85k
        if (!(b = cram_read_block(fd))) {
4494
74
            cram_free_container(c);
4495
74
            return NULL;
4496
74
        }
4497
1.78k
        if (cram_uncompress_block(b) != 0) {
4498
1.36k
            cram_free_container(c);
4499
1.36k
            cram_free_block(b);
4500
1.36k
            return NULL;
4501
1.36k
        }
4502
4503
417
        len = b->comp_size + 2 + 4*(CRAM_MAJOR_VERS(fd->version) >= 3) +
4504
417
            fd->vv.varint_size(b->content_id) +
4505
417
            fd->vv.varint_size(b->uncomp_size) +
4506
417
            fd->vv.varint_size(b->comp_size);
4507
4508
        /* Extract header from 1st block */
4509
417
        if (-1 == int32_get_blk(b, &header_len) ||
4510
360
            header_len < 0 || /* Spec. says signed...  why? */
4511
353
            b->uncomp_size - 4 < header_len) {
4512
87
            cram_free_container(c);
4513
87
            cram_free_block(b);
4514
87
            return NULL;
4515
87
        }
4516
330
        if (NULL == (header = malloc((size_t) header_len+1))) {
4517
0
            cram_free_container(c);
4518
0
            cram_free_block(b);
4519
0
            return NULL;
4520
0
        }
4521
330
        memcpy(header, BLOCK_END(b), header_len);
4522
330
        header[header_len] = '\0';
4523
330
        cram_free_block(b);
4524
4525
        /* Consume any remaining blocks */
4526
810
        for (i = 1; i < c->num_blocks; i++) {
4527
501
            if (!(b = cram_read_block(fd))) {
4528
21
                cram_free_container(c);
4529
21
                free(header);
4530
21
                return NULL;
4531
21
            }
4532
480
            len += b->comp_size + 2 + 4*(CRAM_MAJOR_VERS(fd->version) >= 3) +
4533
480
                fd->vv.varint_size(b->content_id) +
4534
480
                fd->vv.varint_size(b->uncomp_size) +
4535
480
                fd->vv.varint_size(b->comp_size);
4536
480
            cram_free_block(b);
4537
480
        }
4538
4539
309
        if (c->length > 0 && len > 0 && c->length > len) {
4540
            // Consume padding
4541
11
            char *pads = malloc(c->length - len);
4542
11
            if (!pads) {
4543
0
                cram_free_container(c);
4544
0
                free(header);
4545
0
                return NULL;
4546
0
            }
4547
4548
11
            if (c->length - len != hread(fd->fp, pads, c->length - len)) {
4549
6
                cram_free_container(c);
4550
6
                free(header);
4551
6
                free(pads);
4552
6
                return NULL;
4553
6
            }
4554
5
            free(pads);
4555
5
        }
4556
4557
303
        cram_free_container(c);
4558
303
    }
4559
4560
    /* Parse */
4561
9.57k
    hdr = sam_hdr_init();
4562
9.57k
    if (!hdr) {
4563
0
        free(header);
4564
0
        return NULL;
4565
0
    }
4566
4567
9.57k
    if (-1 == sam_hdr_add_lines(hdr, header, header_len)) {
4568
115
        free(header);
4569
115
        sam_hdr_destroy(hdr);
4570
115
        return NULL;
4571
115
    }
4572
4573
9.45k
    hdr->l_text = header_len;
4574
9.45k
    hdr->text = header;
4575
4576
9.45k
    return hdr;
4577
4578
9.57k
}
4579
4580
/*
4581
 * Converts 'in' to a full pathname to store in out.
4582
 * Out must be at least PATH_MAX bytes long.
4583
 */
4584
0
static void full_path(char *out, char *in) {
4585
0
    size_t in_l = strlen(in);
4586
0
    if (hisremote(in)) {
4587
0
        if (in_l > PATH_MAX) {
4588
0
            hts_log_error("Reference path is longer than %d", PATH_MAX);
4589
0
            return;
4590
0
        }
4591
0
        strncpy(out, in, PATH_MAX-1);
4592
0
        out[PATH_MAX-1] = 0;
4593
0
        return;
4594
0
    }
4595
0
    if (*in == '/' ||
4596
        // Windows paths
4597
0
        (in_l > 3 && toupper_c(*in) >= 'A'  && toupper_c(*in) <= 'Z' &&
4598
0
         in[1] == ':' && (in[2] == '/' || in[2] == '\\'))) {
4599
0
        strncpy(out, in, PATH_MAX-1);
4600
0
        out[PATH_MAX-1] = 0;
4601
0
    } else {
4602
0
        size_t len;
4603
4604
        // unable to get dir or out+in is too long
4605
0
        if (!getcwd(out, PATH_MAX) ||
4606
0
            (len = strlen(out))+1+strlen(in) >= PATH_MAX) {
4607
0
            strncpy(out, in, PATH_MAX-1);
4608
0
            out[PATH_MAX-1] = 0;
4609
0
            return;
4610
0
        }
4611
4612
0
        snprintf(out+len, PATH_MAX - len, "/%s", in);
4613
4614
        // FIXME: cope with `pwd`/../../../foo.fa ?
4615
0
    }
4616
0
}
4617
4618
/*
4619
 * Writes a CRAM SAM header.
4620
 * Returns 0 on success
4621
 *        -1 on failure
4622
 */
4623
10.2k
int cram_write_SAM_hdr(cram_fd *fd, sam_hdr_t *hdr) {
4624
10.2k
    size_t header_len;
4625
10.2k
    int blank_block = (CRAM_MAJOR_VERS(fd->version) >= 3);
4626
4627
    /* Write CRAM MAGIC if not yet written. */
4628
10.2k
    if (fd->file_def->major_version == 0) {
4629
10.2k
        fd->file_def->major_version = CRAM_MAJOR_VERS(fd->version);
4630
10.2k
        fd->file_def->minor_version = CRAM_MINOR_VERS(fd->version);
4631
10.2k
        if (0 != cram_write_file_def(fd, fd->file_def))
4632
0
            return -1;
4633
10.2k
    }
4634
4635
    /* 1.0 requires an UNKNOWN read-group */
4636
10.2k
    if (CRAM_MAJOR_VERS(fd->version) == 1) {
4637
0
        if (!sam_hrecs_find_rg(hdr->hrecs, "UNKNOWN"))
4638
0
            if (sam_hdr_add_line(hdr, "RG",
4639
0
                            "ID", "UNKNOWN", "SM", "UNKNOWN", NULL))
4640
0
                return -1;
4641
0
    }
4642
4643
10.2k
    if (-1 == refs_from_header(fd))
4644
0
        return -1;
4645
10.2k
    if (-1 == refs2id(fd->refs, fd->header))
4646
0
        return -1;
4647
4648
    /* Fix M5 strings */
4649
10.2k
    if (fd->refs && !fd->no_ref && fd->embed_ref <= 1) {
4650
10.2k
        int i;
4651
10.4k
        for (i = 0; i < hdr->hrecs->nref; i++) {
4652
3.44k
            sam_hrec_type_t *ty;
4653
3.44k
            char *ref;
4654
4655
3.44k
            if (!(ty = sam_hrecs_find_type_id(hdr->hrecs, "SQ", "SN", hdr->hrecs->ref[i].name)))
4656
0
                return -1;
4657
4658
3.44k
            if (!sam_hrecs_find_key(ty, "M5", NULL)) {
4659
3.30k
                char unsigned buf[16];
4660
3.30k
                char buf2[33];
4661
3.30k
                hts_pos_t rlen;
4662
3.30k
                hts_md5_context *md5;
4663
4664
3.30k
                if (!fd->refs ||
4665
3.30k
                    !fd->refs->ref_id ||
4666
3.30k
                    !fd->refs->ref_id[i]) {
4667
0
                    return -1;
4668
0
                }
4669
3.30k
                rlen = fd->refs->ref_id[i]->length;
4670
3.30k
                ref = cram_get_ref(fd, i, 1, rlen);
4671
3.30k
                if (NULL == ref) {
4672
3.30k
                    if (fd->embed_ref == -1) {
4673
                        // auto embed-ref
4674
3.30k
                        hts_log_warning("No M5 tags present and could not "
4675
3.30k
                                        "find reference");
4676
3.30k
                        hts_log_warning("Enabling embed_ref=2 option");
4677
3.30k
                        hts_log_warning("NOTE: the CRAM file will be bigger "
4678
3.30k
                                        "than using an external reference");
4679
3.30k
                        pthread_mutex_lock(&fd->ref_lock);
4680
                        // Best guess.  It may be unmapped data with broken
4681
                        // headers, in which case this will get ignored.
4682
3.30k
                        fd->embed_ref = 2;
4683
3.30k
                        pthread_mutex_unlock(&fd->ref_lock);
4684
3.30k
                        break;
4685
3.30k
                    }
4686
0
                    return -1;
4687
3.30k
                }
4688
0
                rlen = fd->refs->ref_id[i]->length; /* In case it just loaded */
4689
0
                if (!(md5 = hts_md5_init()))
4690
0
                    return -1;
4691
0
                if (HTS_POS_MAX <= ULONG_MAX) {
4692
                    // Platforms with 64-bit unsigned long update in one go
4693
0
                    hts_md5_update(md5, ref, rlen);
4694
0
                } else {
4695
                    // Those with 32-bit ulong (Windows) may have to loop
4696
                    // over epic references
4697
0
                    hts_pos_t pos = 0;
4698
0
                    while (rlen - pos > ULONG_MAX) {
4699
0
                        hts_md5_update(md5, ref + pos, ULONG_MAX);
4700
0
                        pos += ULONG_MAX;
4701
0
                    }
4702
0
                    hts_md5_update(md5, ref + pos, (unsigned long)(rlen - pos));
4703
0
                }
4704
0
                hts_md5_final(buf, md5);
4705
0
                hts_md5_destroy(md5);
4706
0
                cram_ref_decr(fd->refs, i);
4707
4708
0
                hts_md5_hex(buf2, buf);
4709
0
                fd->refs->ref_id[i]->validated_md5 = 1;
4710
0
                if (sam_hdr_update_line(hdr, "SQ", "SN", hdr->hrecs->ref[i].name, "M5", buf2, NULL))
4711
0
                    return -1;
4712
0
            }
4713
4714
135
            if (fd->ref_fn) {
4715
0
                char ref_fn[PATH_MAX];
4716
0
                full_path(ref_fn, fd->ref_fn);
4717
0
                if (sam_hdr_update_line(hdr, "SQ", "SN", hdr->hrecs->ref[i].name, "UR", ref_fn, NULL))
4718
0
                    return -1;
4719
0
            }
4720
135
        }
4721
10.2k
    }
4722
4723
10.2k
    if (fd->remove_ur) {
4724
0
        if (sam_hdr_remove_tag_all(hdr, "SQ", "UR") < 0) {
4725
0
            hts_log_error("Unable to remove UR tags");
4726
0
            return -1;
4727
0
        }
4728
0
    }
4729
4730
    /* Length */
4731
10.2k
    header_len = sam_hdr_length(hdr);
4732
10.2k
    if (header_len > INT32_MAX) {
4733
0
        hts_log_error("Header is too long for CRAM format");
4734
0
        return -1;
4735
0
    }
4736
10.2k
    if (CRAM_MAJOR_VERS(fd->version) == 1) {
4737
0
        if (-1 == int32_encode(fd, header_len))
4738
0
            return -1;
4739
4740
        /* Text data */
4741
0
        if (header_len != hwrite(fd->fp, sam_hdr_str(hdr), header_len))
4742
0
            return -1;
4743
10.2k
    } else {
4744
        /* Create block(s) inside a container */
4745
10.2k
        cram_block *b = cram_new_block(FILE_HEADER, 0);
4746
10.2k
        cram_container *c = cram_new_container(0, 0);
4747
10.2k
        int padded_length;
4748
10.2k
        char *pads;
4749
10.2k
        int is_cram_3 = (CRAM_MAJOR_VERS(fd->version) >= 3);
4750
4751
10.2k
        if (!b || !c) {
4752
0
            if (b) cram_free_block(b);
4753
0
            if (c) cram_free_container(c);
4754
0
            return -1;
4755
0
        }
4756
4757
10.2k
        if (int32_put_blk(b, header_len) < 0)
4758
0
            return -1;
4759
10.2k
        if (header_len)
4760
5.35k
            BLOCK_APPEND(b, sam_hdr_str(hdr), header_len);
4761
10.2k
        BLOCK_UPLEN(b);
4762
4763
        // Compress header block if V3.0 and above
4764
10.2k
        if (CRAM_MAJOR_VERS(fd->version) >= 3)
4765
10.2k
            if (cram_compress_block(fd, b, NULL, -1, -1) < 0)
4766
0
                return -1;
4767
4768
10.2k
        if (blank_block) {
4769
10.2k
            c->length = b->comp_size + 2 + 4*is_cram_3 +
4770
10.2k
                fd->vv.varint_size(b->content_id)   +
4771
10.2k
                fd->vv.varint_size(b->uncomp_size)  +
4772
10.2k
                fd->vv.varint_size(b->comp_size);
4773
4774
10.2k
            c->num_blocks = 2;
4775
10.2k
            c->num_landmarks = 2;
4776
10.2k
            if (!(c->landmark = malloc(2*sizeof(*c->landmark)))) {
4777
0
                cram_free_block(b);
4778
0
                cram_free_container(c);
4779
0
                return -1;
4780
0
            }
4781
10.2k
            c->landmark[0] = 0;
4782
10.2k
            c->landmark[1] = c->length;
4783
4784
            // Plus extra storage for uncompressed secondary blank block
4785
10.2k
            padded_length = MIN(c->length*.5, 10000);
4786
10.2k
            c->length += padded_length + 2 + 4*is_cram_3 +
4787
10.2k
                fd->vv.varint_size(b->content_id) +
4788
10.2k
                fd->vv.varint_size(padded_length)*2;
4789
10.2k
        } else {
4790
            // Pad the block instead.
4791
0
            c->num_blocks = 1;
4792
0
            c->num_landmarks = 1;
4793
0
            if (!(c->landmark = malloc(sizeof(*c->landmark))))
4794
0
                return -1;
4795
0
            c->landmark[0] = 0;
4796
4797
0
            padded_length = MAX(c->length*1.5, 10000) - c->length;
4798
4799
0
            c->length = b->comp_size + padded_length +
4800
0
                2 + 4*is_cram_3 +
4801
0
                fd->vv.varint_size(b->content_id)   +
4802
0
                fd->vv.varint_size(b->uncomp_size)  +
4803
0
                fd->vv.varint_size(b->comp_size);
4804
4805
0
            if (NULL == (pads = calloc(1, padded_length))) {
4806
0
                cram_free_block(b);
4807
0
                cram_free_container(c);
4808
0
                return -1;
4809
0
            }
4810
0
            BLOCK_APPEND(b, pads, padded_length);
4811
0
            BLOCK_UPLEN(b);
4812
0
            free(pads);
4813
0
        }
4814
4815
10.2k
        if (-1 == cram_write_container(fd, c)) {
4816
0
            cram_free_block(b);
4817
0
            cram_free_container(c);
4818
0
            return -1;
4819
0
        }
4820
4821
10.2k
        if (-1 == cram_write_block(fd, b)) {
4822
0
            cram_free_block(b);
4823
0
            cram_free_container(c);
4824
0
            return -1;
4825
0
        }
4826
4827
10.2k
        if (blank_block) {
4828
10.2k
            BLOCK_RESIZE(b, padded_length);
4829
10.2k
            memset(BLOCK_DATA(b), 0, padded_length);
4830
10.2k
            BLOCK_SIZE(b) = padded_length;
4831
10.2k
            BLOCK_UPLEN(b);
4832
10.2k
            b->method = RAW;
4833
10.2k
            if (-1 == cram_write_block(fd, b)) {
4834
0
                cram_free_block(b);
4835
0
                cram_free_container(c);
4836
0
                return -1;
4837
0
            }
4838
10.2k
        }
4839
4840
10.2k
        cram_free_block(b);
4841
10.2k
        cram_free_container(c);
4842
10.2k
    }
4843
4844
10.2k
    if (0 != hflush(fd->fp))
4845
0
        return -1;
4846
4847
10.2k
    RP("=== Finishing saving header ===\n");
4848
4849
10.2k
    return 0;
4850
4851
0
 block_err:
4852
0
    return -1;
4853
10.2k
}
4854
4855
/* ----------------------------------------------------------------------
4856
 * The top-level cram opening, closing and option handling
4857
 */
4858
4859
/*
4860
 * Sets CRAM variable sized integer decode function tables.
4861
 * CRAM 1, 2, and 3.x all used ITF8 for uint32 and UTF8 for uint64.
4862
 * CRAM 4.x uses the same encoding mechanism for 32-bit and 64-bit
4863
 * (or anything in between), but also now supports signed values.
4864
 *
4865
 * Version is the CRAM major version number.
4866
 * vv is the vector table (probably &cram_fd->vv)
4867
 */
4868
22.3k
static void cram_init_varint(varint_vec *vv, int version) {
4869
22.3k
    vv->varint_get32 = safe_itf8_get;
4870
22.3k
    vv->varint_get32s = safe_itf8_get;
4871
22.3k
    vv->varint_get64 = safe_ltf8_get;
4872
22.3k
    vv->varint_get64s = safe_ltf8_get;
4873
22.3k
    vv->varint_put32 = safe_itf8_put;
4874
22.3k
    vv->varint_put32s = safe_itf8_put;
4875
22.3k
    vv->varint_put64 = safe_ltf8_put;
4876
22.3k
    vv->varint_put64s = safe_ltf8_put;
4877
22.3k
    vv->varint_put32_blk = itf8_put_blk;
4878
22.3k
    vv->varint_put32s_blk = itf8_put_blk;
4879
22.3k
    vv->varint_put64_blk = ltf8_put_blk;
4880
22.3k
    vv->varint_put64s_blk = ltf8_put_blk;
4881
22.3k
    vv->varint_size = itf8_size;
4882
22.3k
    vv->varint_decode32_crc = itf8_decode_crc;
4883
22.3k
    vv->varint_decode32s_crc = itf8_decode_crc;
4884
22.3k
    vv->varint_decode64_crc = ltf8_decode_crc;
4885
22.3k
}
4886
4887
/*
4888
 * Initialises the lookup tables. These could be global statics, but they're
4889
 * clumsy to setup in a multi-threaded environment unless we generate
4890
 * verbatim code and include that.
4891
 */
4892
22.3k
static void cram_init_tables(cram_fd *fd) {
4893
22.3k
    int i;
4894
4895
22.3k
    memset(fd->L1, 4, 256);
4896
22.3k
    fd->L1['A'] = 0; fd->L1['a'] = 0;
4897
22.3k
    fd->L1['C'] = 1; fd->L1['c'] = 1;
4898
22.3k
    fd->L1['G'] = 2; fd->L1['g'] = 2;
4899
22.3k
    fd->L1['T'] = 3; fd->L1['t'] = 3;
4900
4901
22.3k
    memset(fd->L2, 5, 256);
4902
22.3k
    fd->L2['A'] = 0; fd->L2['a'] = 0;
4903
22.3k
    fd->L2['C'] = 1; fd->L2['c'] = 1;
4904
22.3k
    fd->L2['G'] = 2; fd->L2['g'] = 2;
4905
22.3k
    fd->L2['T'] = 3; fd->L2['t'] = 3;
4906
22.3k
    fd->L2['N'] = 4; fd->L2['n'] = 4;
4907
4908
22.3k
    if (CRAM_MAJOR_VERS(fd->version) == 1) {
4909
4.77M
        for (i = 0; i < 0x200; i++) {
4910
4.76M
            int f = 0;
4911
4912
4.76M
            if (i & CRAM_FPAIRED)      f |= BAM_FPAIRED;
4913
4.76M
            if (i & CRAM_FPROPER_PAIR) f |= BAM_FPROPER_PAIR;
4914
4.76M
            if (i & CRAM_FUNMAP)       f |= BAM_FUNMAP;
4915
4.76M
            if (i & CRAM_FREVERSE)     f |= BAM_FREVERSE;
4916
4.76M
            if (i & CRAM_FREAD1)       f |= BAM_FREAD1;
4917
4.76M
            if (i & CRAM_FREAD2)       f |= BAM_FREAD2;
4918
4.76M
            if (i & CRAM_FSECONDARY)   f |= BAM_FSECONDARY;
4919
4.76M
            if (i & CRAM_FQCFAIL)      f |= BAM_FQCFAIL;
4920
4.76M
            if (i & CRAM_FDUP)         f |= BAM_FDUP;
4921
4922
4.76M
            fd->bam_flag_swap[i]  = f;
4923
4.76M
        }
4924
4925
38.1M
        for (i = 0; i < 0x1000; i++) {
4926
38.0M
            int g = 0;
4927
4928
38.0M
            if (i & BAM_FPAIRED)           g |= CRAM_FPAIRED;
4929
38.0M
            if (i & BAM_FPROPER_PAIR)  g |= CRAM_FPROPER_PAIR;
4930
38.0M
            if (i & BAM_FUNMAP)        g |= CRAM_FUNMAP;
4931
38.0M
            if (i & BAM_FREVERSE)      g |= CRAM_FREVERSE;
4932
38.0M
            if (i & BAM_FREAD1)        g |= CRAM_FREAD1;
4933
38.0M
            if (i & BAM_FREAD2)        g |= CRAM_FREAD2;
4934
38.0M
            if (i & BAM_FSECONDARY)    g |= CRAM_FSECONDARY;
4935
38.0M
            if (i & BAM_FQCFAIL)       g |= CRAM_FQCFAIL;
4936
38.0M
            if (i & BAM_FDUP)          g |= CRAM_FDUP;
4937
4938
38.0M
            fd->cram_flag_swap[i] = g;
4939
38.0M
        }
4940
13.0k
    } else {
4941
        /* NOP */
4942
53.5M
        for (i = 0; i < 0x1000; i++)
4943
53.5M
            fd->bam_flag_swap[i] = i;
4944
53.5M
        for (i = 0; i < 0x1000; i++)
4945
53.5M
            fd->cram_flag_swap[i] = i;
4946
13.0k
    }
4947
4948
22.3k
    memset(fd->cram_sub_matrix, 4, 32*32);
4949
738k
    for (i = 0; i < 32; i++) {
4950
715k
        fd->cram_sub_matrix[i]['A'&0x1f]=0;
4951
715k
        fd->cram_sub_matrix[i]['C'&0x1f]=1;
4952
715k
        fd->cram_sub_matrix[i]['G'&0x1f]=2;
4953
715k
        fd->cram_sub_matrix[i]['T'&0x1f]=3;
4954
715k
        fd->cram_sub_matrix[i]['N'&0x1f]=4;
4955
715k
    }
4956
134k
    for (i = 0; i < 20; i+=4) {
4957
111k
        int j;
4958
2.34M
        for (j = 0; j < 20; j++) {
4959
2.23M
            fd->cram_sub_matrix["ACGTN"[i>>2]&0x1f][j]=3;
4960
2.23M
            fd->cram_sub_matrix["ACGTN"[i>>2]&0x1f][j]=3;
4961
2.23M
            fd->cram_sub_matrix["ACGTN"[i>>2]&0x1f][j]=3;
4962
2.23M
            fd->cram_sub_matrix["ACGTN"[i>>2]&0x1f][j]=3;
4963
2.23M
        }
4964
111k
        fd->cram_sub_matrix["ACGTN"[i>>2]&0x1f][CRAM_SUBST_MATRIX[i+0]&0x1f]=0;
4965
111k
        fd->cram_sub_matrix["ACGTN"[i>>2]&0x1f][CRAM_SUBST_MATRIX[i+1]&0x1f]=1;
4966
111k
        fd->cram_sub_matrix["ACGTN"[i>>2]&0x1f][CRAM_SUBST_MATRIX[i+2]&0x1f]=2;
4967
111k
        fd->cram_sub_matrix["ACGTN"[i>>2]&0x1f][CRAM_SUBST_MATRIX[i+3]&0x1f]=3;
4968
111k
    }
4969
4970
22.3k
    cram_init_varint(&fd->vv, CRAM_MAJOR_VERS(fd->version));
4971
22.3k
}
4972
4973
// Default version numbers for CRAM
4974
static int major_version = 3;
4975
static int minor_version = 1;
4976
4977
/*
4978
 * Opens a CRAM file for read (mode "rb") or write ("wb").
4979
 * The filename may be "-" to indicate stdin or stdout.
4980
 *
4981
 * Returns file handle on success
4982
 *         NULL on failure.
4983
 */
4984
0
cram_fd *cram_open(const char *filename, const char *mode) {
4985
0
    hFILE *fp;
4986
0
    cram_fd *fd;
4987
0
    char fmode[3]= { mode[0], '\0', '\0' };
4988
4989
0
    if (strlen(mode) > 1 && (mode[1] == 'b' || mode[1] == 'c')) {
4990
0
        fmode[1] = 'b';
4991
0
    }
4992
4993
0
    fp = hopen(filename, fmode);
4994
0
    if (!fp)
4995
0
        return NULL;
4996
4997
0
    fd = cram_dopen(fp, filename, mode);
4998
0
    if (!fd)
4999
0
        hclose_abruptly(fp);
5000
5001
0
    return fd;
5002
0
}
5003
5004
/* Opens an existing stream for reading or writing.
5005
 *
5006
 * Returns file handle on success;
5007
 *         NULL on failure.
5008
 */
5009
22.3k
cram_fd *cram_dopen(hFILE *fp, const char *filename, const char *mode) {
5010
22.3k
    int i;
5011
22.3k
    const char *cp;
5012
22.3k
    cram_fd *fd = calloc(1, sizeof(*fd));
5013
22.3k
    if (!fd)
5014
0
        return NULL;
5015
5016
22.3k
    fd->level = CRAM_DEFAULT_LEVEL;
5017
67.1k
    for (i = 0; mode[i]; i++) {
5018
44.7k
        if (mode[i] >= '0' && mode[i] <= '9') {
5019
0
            fd->level = mode[i] - '0';
5020
0
            break;
5021
0
        }
5022
44.7k
    }
5023
5024
22.3k
    fd->fp = fp;
5025
22.3k
    fd->mode = *mode;
5026
22.3k
    fd->first_container = 0;
5027
22.3k
    fd->curr_position = 0;
5028
5029
22.3k
    if (fd->mode == 'r') {
5030
        /* Reader */
5031
5032
11.3k
        if (!(fd->file_def = cram_read_file_def(fd)))
5033
9
            goto err;
5034
5035
11.3k
        fd->version = fd->file_def->major_version * 256 +
5036
11.3k
            fd->file_def->minor_version;
5037
5038
11.3k
        cram_init_tables(fd);
5039
5040
11.3k
        if (!(fd->header = cram_read_SAM_hdr(fd))) {
5041
1.85k
            cram_free_file_def(fd->file_def);
5042
1.85k
            goto err;
5043
1.85k
        }
5044
5045
11.3k
    } else {
5046
        /* Writer */
5047
11.0k
        cram_file_def *def = calloc(1, sizeof(*def));
5048
11.0k
        if (!def)
5049
0
            return NULL;
5050
5051
11.0k
        fd->file_def = def;
5052
5053
11.0k
        def->magic[0] = 'C';
5054
11.0k
        def->magic[1] = 'R';
5055
11.0k
        def->magic[2] = 'A';
5056
11.0k
        def->magic[3] = 'M';
5057
11.0k
        def->major_version = 0; // Indicator to write file def later.
5058
11.0k
        def->minor_version = 0;
5059
11.0k
        memset(def->file_id, 0, 20);
5060
11.0k
        strncpy(def->file_id, filename, 20);
5061
5062
11.0k
        fd->version = major_version * 256 + minor_version;
5063
11.0k
        cram_init_tables(fd);
5064
5065
        /* SAM header written later along with this file_def */
5066
11.0k
    }
5067
5068
20.5k
    fd->prefix = strdup((cp = strrchr(filename, '/')) ? cp+1 : filename);
5069
20.5k
    if (!fd->prefix)
5070
0
        goto err;
5071
20.5k
    fd->first_base = fd->last_base = -1;
5072
20.5k
    fd->record_counter = 0;
5073
5074
20.5k
    fd->ctr = NULL;
5075
20.5k
    fd->ctr_mt = NULL;
5076
20.5k
    fd->refs  = refs_create();
5077
20.5k
    if (!fd->refs)
5078
0
        goto err;
5079
20.5k
    fd->ref_id = -2;
5080
20.5k
    fd->ref = NULL;
5081
5082
20.5k
    fd->decode_md = 0;
5083
20.5k
    fd->seqs_per_slice = SEQS_PER_SLICE;
5084
20.5k
    fd->bases_per_slice = BASES_PER_SLICE;
5085
20.5k
    fd->slices_per_container = SLICE_PER_CNT;
5086
20.5k
    fd->embed_ref = -1; // automatic selection
5087
20.5k
    fd->no_ref = 0;
5088
20.5k
    fd->no_ref_counter = 0;
5089
20.5k
    fd->ap_delta = 0;
5090
20.5k
    fd->ignore_md5 = 0;
5091
20.5k
    fd->lossy_read_names = 0;
5092
20.5k
    fd->use_bz2 = 0;
5093
20.5k
    fd->use_rans = (CRAM_MAJOR_VERS(fd->version) >= 3);
5094
20.5k
    fd->use_tok = (CRAM_MAJOR_VERS(fd->version) >= 3) && (CRAM_MINOR_VERS(fd->version) >= 1);
5095
20.5k
    fd->use_lzma = 0;
5096
20.5k
    fd->multi_seq = -1;
5097
20.5k
    fd->multi_seq_user = -1;
5098
20.5k
    fd->unsorted   = 0;
5099
20.5k
    fd->shared_ref = 0;
5100
20.5k
    fd->store_md = 0;
5101
20.5k
    fd->store_nm = 0;
5102
20.5k
    fd->last_RI_count = 0;
5103
5104
20.5k
    fd->index       = NULL;
5105
20.5k
    fd->own_pool    = 0;
5106
20.5k
    fd->pool        = NULL;
5107
20.5k
    fd->rqueue      = NULL;
5108
20.5k
    fd->job_pending = NULL;
5109
20.5k
    fd->ooc         = 0;
5110
20.5k
    fd->required_fields = INT_MAX;
5111
5112
20.5k
    pthread_mutex_init(&fd->metrics_lock, NULL);
5113
20.5k
    pthread_mutex_init(&fd->ref_lock, NULL);
5114
20.5k
    pthread_mutex_init(&fd->range_lock, NULL);
5115
20.5k
    pthread_mutex_init(&fd->bam_list_lock, NULL);
5116
5117
984k
    for (i = 0; i < DS_END; i++) {
5118
964k
        fd->m[i] = cram_new_metrics();
5119
964k
        if (!fd->m[i])
5120
0
            goto err;
5121
964k
    }
5122
5123
20.5k
    if (!(fd->tags_used = kh_init(m_metrics)))
5124
0
        goto err;
5125
5126
20.5k
    fd->range.refid = -2; // no ref.
5127
20.5k
    fd->eof = 1;          // See samtools issue #150
5128
20.5k
    fd->ref_fn = NULL;
5129
5130
20.5k
    fd->bl = NULL;
5131
5132
    /* Initialise dummy refs from the @SQ headers */
5133
20.5k
    if (-1 == refs_from_header(fd))
5134
0
        goto err;
5135
5136
20.5k
    return fd;
5137
5138
1.86k
 err:
5139
1.86k
    if (fd)
5140
1.86k
        free(fd);
5141
5142
1.86k
    return NULL;
5143
20.5k
}
5144
5145
/*
5146
 * Seek within a CRAM file.
5147
 *
5148
 * Returns 0 on success
5149
 *        -1 on failure
5150
 */
5151
0
int cram_seek(cram_fd *fd, off_t offset, int whence) {
5152
0
    fd->ooc = 0;
5153
5154
0
    cram_drain_rqueue(fd);
5155
5156
0
    return hseek(fd->fp, offset, whence) >= 0 ? 0 : -1;
5157
0
}
5158
5159
/*
5160
 * Flushes a CRAM file.
5161
 * Useful for when writing to stdout without wishing to close the stream.
5162
 *
5163
 * Returns 0 on success
5164
 *        -1 on failure
5165
 */
5166
0
int cram_flush(cram_fd *fd) {
5167
0
    if (!fd)
5168
0
        return -1;
5169
5170
0
    int ret = 0;
5171
5172
0
    if (fd->mode == 'w' && fd->ctr) {
5173
0
        if(fd->ctr->slice)
5174
0
            cram_update_curr_slice(fd->ctr, fd->version);
5175
5176
0
        if (-1 == cram_flush_container_mt(fd, fd->ctr))
5177
0
            ret = -1;
5178
5179
0
        cram_free_container(fd->ctr);
5180
0
        if (fd->ctr_mt == fd->ctr)
5181
0
            fd->ctr_mt = NULL;
5182
0
        fd->ctr = NULL;
5183
0
    }
5184
5185
0
    return ret;
5186
0
}
5187
5188
/*
5189
 * Writes an EOF block to a CRAM file.
5190
 *
5191
 * Returns 0 on success
5192
 *        -1 on failure
5193
 */
5194
10.0k
int cram_write_eof_block(cram_fd *fd) {
5195
    // EOF block is a container with special values to aid detection
5196
10.0k
    if (CRAM_MAJOR_VERS(fd->version) >= 2) {
5197
        // Empty container with
5198
        //   ref_seq_id -1
5199
        //   start pos 0x454f46 ("EOF")
5200
        //   span 0
5201
        //   nrec 0
5202
        //   counter 0
5203
        //   nbases 0
5204
        //   1 block (landmark 0)
5205
        //   (CRC32)
5206
10.0k
        cram_container c;
5207
10.0k
        memset(&c, 0, sizeof(c));
5208
10.0k
        c.ref_seq_id = -1;
5209
10.0k
        c.ref_seq_start = 0x454f46; // "EOF"
5210
10.0k
        c.ref_seq_span = 0;
5211
10.0k
        c.record_counter = 0;
5212
10.0k
        c.num_bases = 0;
5213
10.0k
        c.num_blocks = 1;
5214
10.0k
        int32_t land[1] = {0};
5215
10.0k
        c.landmark = land;
5216
5217
        // An empty compression header block with
5218
        //   method raw (0)
5219
        //   type comp header (1)
5220
        //   content id 0
5221
        //   block contents size 6
5222
        //   raw size 6
5223
        //     empty preservation map (01 00)
5224
        //     empty data series map (01 00)
5225
        //     empty tag map (01 00)
5226
        //   block CRC
5227
10.0k
        cram_block_compression_hdr ch;
5228
10.0k
        memset(&ch, 0, sizeof(ch));
5229
10.0k
        c.comp_hdr_block = cram_encode_compression_header(fd, &c, &ch, 0);
5230
5231
10.0k
        c.length = c.comp_hdr_block->byte            // Landmark[0]
5232
10.0k
            + 5                                      // block struct
5233
10.0k
            + 4*(CRAM_MAJOR_VERS(fd->version) >= 3); // CRC
5234
10.0k
        if (cram_write_container(fd, &c) < 0 ||
5235
10.0k
            cram_write_block(fd, c.comp_hdr_block) < 0) {
5236
0
            cram_close(fd);
5237
0
            cram_free_block(c.comp_hdr_block);
5238
0
            return -1;
5239
0
        }
5240
10.0k
        if (ch.preservation_map)
5241
0
            kh_destroy(map, ch.preservation_map);
5242
10.0k
        cram_free_block(c.comp_hdr_block);
5243
5244
        // V2.1 bytes
5245
        // 0b 00 00 00 ff ff ff ff 0f // Cont HDR: size, ref seq id
5246
        // e0 45 4f 46 00 00 00       // Cont HDR: pos, span, nrec, counter
5247
        // 00 01 00                   // Cont HDR: nbase, nblk, landmark
5248
        // 00 01 00 06 06             // Comp.HDR blk
5249
        // 01 00 01 00 01 00          // Comp.HDR blk
5250
5251
        // V3.0 bytes:
5252
        // 0f 00 00 00 ff ff ff ff 0f // Cont HDR: size, ref seq id
5253
        // e0 45 4f 46 00 00 00       // Cont HDR: pos, span, nrec, counter
5254
        // 00 01 00                   // Cont HDR: nbase, nblk, landmark
5255
        // 05 bd d9 4f                // CRC32
5256
        // 00 01 00 06 06             // Comp.HDR blk
5257
        // 01 00 01 00 01 00          // Comp.HDR blk
5258
        // ee 63 01 4b                // CRC32
5259
10.0k
    }
5260
5261
10.0k
    return 0;
5262
10.0k
}
5263
5264
/*
5265
 * Closes a CRAM file.
5266
 * Returns 0 on success
5267
 *        -1 on failure
5268
 */
5269
20.5k
int cram_close(cram_fd *fd) {
5270
20.5k
    bam_list *bl, *next;
5271
20.5k
    int i, ret = 0;
5272
5273
20.5k
    if (!fd)
5274
0
        return -1;
5275
5276
20.5k
    if (fd->mode == 'w' && fd->ctr) {
5277
5.44k
        if(fd->ctr->slice)
5278
5.44k
            cram_update_curr_slice(fd->ctr, fd->version);
5279
5280
5.44k
        if (-1 == cram_flush_container_mt(fd, fd->ctr))
5281
988
            ret = -1;
5282
5.44k
    }
5283
5284
20.5k
    if (fd->mode != 'w')
5285
9.45k
        cram_drain_rqueue(fd);
5286
5287
20.5k
    if (fd->pool && fd->eof >= 0 && fd->rqueue) {
5288
0
        hts_tpool_process_flush(fd->rqueue);
5289
5290
0
        if (0 != cram_flush_result(fd))
5291
0
            ret = -1;
5292
5293
0
        if (fd->mode == 'w')
5294
0
            fd->ctr = NULL; // prevent double freeing
5295
5296
        //fprintf(stderr, "CRAM: destroy queue %p\n", fd->rqueue);
5297
5298
0
        hts_tpool_process_destroy(fd->rqueue);
5299
0
    }
5300
5301
20.5k
    pthread_mutex_destroy(&fd->metrics_lock);
5302
20.5k
    pthread_mutex_destroy(&fd->ref_lock);
5303
20.5k
    pthread_mutex_destroy(&fd->range_lock);
5304
20.5k
    pthread_mutex_destroy(&fd->bam_list_lock);
5305
5306
20.5k
    if (ret == 0 && fd->mode == 'w') {
5307
        /* Write EOF block */
5308
10.0k
        if (0 != cram_write_eof_block(fd))
5309
0
            ret = -1;
5310
10.0k
    }
5311
5312
25.2k
    for (bl = fd->bl; bl; bl = next) {
5313
4.75k
        next = bl->next;
5314
4.75k
        free_bam_list(bl->bams, bl->nbams);
5315
4.75k
        free(bl);
5316
4.75k
    }
5317
5318
20.5k
    if (hclose(fd->fp) != 0)
5319
0
        ret = -1;
5320
5321
20.5k
    if (fd->file_def)
5322
20.5k
        cram_free_file_def(fd->file_def);
5323
5324
20.5k
    if (fd->header)
5325
19.8k
        sam_hdr_destroy(fd->header);
5326
5327
20.5k
    free(fd->prefix);
5328
5329
20.5k
    if (fd->ctr)
5330
11.8k
        cram_free_container(fd->ctr);
5331
5332
20.5k
    if (fd->ctr_mt && fd->ctr_mt != fd->ctr)
5333
156
        cram_free_container(fd->ctr_mt);
5334
5335
20.5k
    if (fd->refs)
5336
20.5k
        refs_free(fd->refs);
5337
20.5k
    if (fd->ref_free)
5338
0
        free(fd->ref_free);
5339
5340
984k
    for (i = 0; i < DS_END; i++)
5341
964k
        if (fd->m[i])
5342
964k
            free(fd->m[i]);
5343
5344
20.5k
    if (fd->tags_used) {
5345
20.5k
        khint_t k;
5346
5347
39.1k
        for (k = kh_begin(fd->tags_used); k != kh_end(fd->tags_used); k++) {
5348
18.6k
            if (kh_exist(fd->tags_used, k))
5349
8.69k
                free(kh_val(fd->tags_used, k));
5350
18.6k
        }
5351
5352
20.5k
        kh_destroy(m_metrics, fd->tags_used);
5353
20.5k
    }
5354
5355
20.5k
    if (fd->index)
5356
0
        cram_index_free(fd);
5357
5358
20.5k
    if (fd->own_pool && fd->pool)
5359
0
        hts_tpool_destroy(fd->pool);
5360
5361
20.5k
    if (fd->idxfp)
5362
0
        if (bgzf_close(fd->idxfp) < 0)
5363
0
            ret = -1;
5364
5365
20.5k
    free(fd);
5366
5367
20.5k
    return ret;
5368
20.5k
}
5369
5370
/*
5371
 * Returns 1 if we hit an EOF while reading.
5372
 */
5373
16.5k
int cram_eof(cram_fd *fd) {
5374
16.5k
    return fd->eof;
5375
16.5k
}
5376
5377
5378
/*
5379
 * Sets options on the cram_fd. See CRAM_OPT_* definitions in cram_structs.h.
5380
 * Use this immediately after opening.
5381
 *
5382
 * Returns 0 on success
5383
 *        -1 on failure
5384
 */
5385
9.45k
int cram_set_option(cram_fd *fd, enum hts_fmt_option opt, ...) {
5386
9.45k
    int r;
5387
9.45k
    va_list args;
5388
5389
9.45k
    va_start(args, opt);
5390
9.45k
    r = cram_set_voption(fd, opt, args);
5391
9.45k
    va_end(args);
5392
5393
9.45k
    return r;
5394
9.45k
}
5395
5396
// Check valid range for options.
5397
#define CHECK_RANGE(v,min,max)                  \
5398
9.45k
    do {                                        \
5399
9.45k
        int val = (v);                          \
5400
9.45k
        if((val) < (min) || (val) > (max)) {    \
5401
9.45k
            errno = ERANGE;                     \
5402
9.45k
            return -1;                          \
5403
9.45k
        }                                       \
5404
9.45k
    } while (0);
5405
5406
/*
5407
 * Sets options on the cram_fd. See CRAM_OPT_* definitions in cram_structs.h.
5408
 * Use this immediately after opening.
5409
 *
5410
 * Returns 0 on success
5411
 *        -1 on failure
5412
 */
5413
9.45k
int cram_set_voption(cram_fd *fd, enum hts_fmt_option opt, va_list args) {
5414
9.45k
    refs_t *refs;
5415
5416
9.45k
    if (!fd) {
5417
0
        errno = EBADF;
5418
0
        return -1;
5419
0
    }
5420
5421
9.45k
    switch (opt) {
5422
9.45k
    case CRAM_OPT_DECODE_MD:
5423
9.45k
        CHECK_RANGE(fd->decode_md = va_arg(args, int), 0, 1);
5424
0
        break;
5425
5426
0
    case CRAM_OPT_PREFIX:
5427
0
        if (fd->prefix)
5428
0
            free(fd->prefix);
5429
0
        if (!(fd->prefix = strdup(va_arg(args, char *))))
5430
0
            return -1;
5431
0
        break;
5432
5433
0
    case CRAM_OPT_VERBOSITY:
5434
0
        break;
5435
5436
0
    case CRAM_OPT_SEQS_PER_SLICE:
5437
0
        CHECK_RANGE(fd->seqs_per_slice = va_arg(args, int), 1, INT_MAX/512);
5438
0
        if (fd->bases_per_slice == BASES_PER_SLICE)
5439
0
            fd->bases_per_slice = fd->seqs_per_slice * 500;
5440
0
        break;
5441
5442
0
    case CRAM_OPT_BASES_PER_SLICE:
5443
0
        CHECK_RANGE(fd->bases_per_slice = va_arg(args, int), 1, INT_MAX);
5444
0
        break;
5445
5446
0
    case CRAM_OPT_SLICES_PER_CONTAINER:
5447
0
        CHECK_RANGE(fd->slices_per_container = va_arg(args, int), 1, 512);
5448
0
        break;
5449
5450
0
    case CRAM_OPT_EMBED_REF:
5451
0
        CHECK_RANGE(fd->embed_ref = va_arg(args, int), -1, 2);
5452
0
        break;
5453
5454
0
    case CRAM_OPT_NO_REF:
5455
0
        CHECK_RANGE(fd->no_ref = va_arg(args, int), 0, 1);
5456
0
        break;
5457
5458
0
    case CRAM_OPT_POS_DELTA:
5459
0
        CHECK_RANGE(fd->ap_delta = va_arg(args, int), 0, 1);
5460
0
        break;
5461
5462
0
    case CRAM_OPT_IGNORE_MD5:
5463
0
        CHECK_RANGE(fd->ignore_md5 = va_arg(args, int), 0, 1);
5464
0
        break;
5465
5466
0
    case CRAM_OPT_LOSSY_NAMES:
5467
0
        CHECK_RANGE(fd->lossy_read_names = va_arg(args, int), 0, INT_MAX);
5468
        // Currently lossy read names required paired (attached) reads.
5469
        // TLEN 0 or being 1 out causes read pairs to be detached, breaking
5470
        // the lossy read name compression, so we have extra options to
5471
        // slacken the exact TLEN round-trip checks.
5472
0
        fd->tlen_approx = fd->lossy_read_names;
5473
0
        fd->tlen_zero = fd->lossy_read_names;
5474
0
        break;
5475
5476
0
    case CRAM_OPT_USE_BZIP2:
5477
0
        CHECK_RANGE(fd->use_bz2 = va_arg(args, int), 0, 1);
5478
0
        break;
5479
5480
0
    case CRAM_OPT_USE_RANS:
5481
0
        CHECK_RANGE(fd->use_rans = va_arg(args, int), 0, 1);
5482
0
        break;
5483
5484
0
    case CRAM_OPT_USE_TOK:
5485
0
        CHECK_RANGE(fd->use_tok = va_arg(args, int), 0, 1);
5486
0
        break;
5487
5488
0
    case CRAM_OPT_USE_FQZ:
5489
0
        CHECK_RANGE(fd->use_fqz = va_arg(args, int), 0, 1);
5490
0
        break;
5491
5492
0
    case CRAM_OPT_USE_ARITH:
5493
0
        CHECK_RANGE(fd->use_arith = va_arg(args, int), 0, 1);
5494
0
        break;
5495
5496
0
    case CRAM_OPT_USE_LZMA:
5497
0
        CHECK_RANGE(fd->use_lzma = va_arg(args, int), 0, 1);
5498
0
        break;
5499
5500
0
    case CRAM_OPT_SHARED_REF:
5501
0
        fd->shared_ref = 1;
5502
0
        refs = va_arg(args, refs_t *);
5503
0
        if (refs != fd->refs) {
5504
0
            if (fd->refs)
5505
0
                refs_free(fd->refs);
5506
0
            fd->refs = refs;
5507
0
            fd->refs->count++;
5508
0
        }
5509
0
        break;
5510
5511
0
    case CRAM_OPT_RANGE: {
5512
0
        int r = cram_seek_to_refpos(fd, va_arg(args, cram_range *));
5513
0
        pthread_mutex_lock(&fd->range_lock);
5514
//        printf("opt range noseek to %p %d:%ld-%ld\n",
5515
//               fd, fd->range.refid, fd->range.start, fd->range.end);
5516
0
        if (fd->range.refid != -2)
5517
0
            fd->required_fields |= SAM_POS;
5518
0
        pthread_mutex_unlock(&fd->range_lock);
5519
0
        return r;
5520
0
    }
5521
5522
0
    case CRAM_OPT_RANGE_NOSEEK: {
5523
        // As per CRAM_OPT_RANGE, but no seeking
5524
0
        pthread_mutex_lock(&fd->range_lock);
5525
0
        cram_range *r = va_arg(args, cram_range *);
5526
0
        fd->range = *r;
5527
0
        if (r->refid == HTS_IDX_NOCOOR) {
5528
0
            fd->range.refid = -1;
5529
0
            fd->range.start = 0;
5530
0
        } else if (r->refid == HTS_IDX_START || r->refid == HTS_IDX_REST) {
5531
0
            fd->range.refid = -2; // special case in cram_next_slice
5532
0
        }
5533
0
        if (fd->range.refid != -2)
5534
0
            fd->required_fields |= SAM_POS;
5535
0
        fd->ooc = 0;
5536
0
        fd->eof = 0;
5537
0
        pthread_mutex_unlock(&fd->range_lock);
5538
0
        return 0;
5539
0
    }
5540
5541
0
    case CRAM_OPT_REFERENCE:
5542
0
        return cram_load_reference(fd, va_arg(args, char *));
5543
5544
0
    case CRAM_OPT_VERSION: {
5545
0
        int major, minor;
5546
0
        char *s = va_arg(args, char *);
5547
0
        if (2 != sscanf(s, "%d.%d", &major, &minor)) {
5548
0
            hts_log_error("Malformed version string %s", s);
5549
0
            return -1;
5550
0
        }
5551
0
        if (!((major == 1 &&  minor == 0) ||
5552
0
              (major == 2 && (minor == 0 || minor == 1)) ||
5553
0
              (major == 3 && (minor == 0 || minor == 1)))) {
5554
0
            hts_log_error("Unknown version string; use 1.0, 2.0, 2.1, "
5555
0
                          "3.0 or 3.1");
5556
0
            errno = EINVAL;
5557
0
            return -1;
5558
0
        }
5559
5560
0
        fd->version = major*256 + minor;
5561
5562
0
        fd->use_rans = (CRAM_MAJOR_VERS(fd->version) >= 3) ? 1 : 0;
5563
5564
0
        fd->use_tok = (CRAM_MAJOR_VERS(fd->version) == 3 &&
5565
0
                       CRAM_MINOR_VERS(fd->version) >= 1);
5566
0
        cram_init_tables(fd);
5567
5568
0
        break;
5569
0
    }
5570
5571
0
    case CRAM_OPT_MULTI_SEQ_PER_SLICE:
5572
0
        CHECK_RANGE(fd->multi_seq_user = fd->multi_seq = va_arg(args, int),
5573
0
                    -1, 1);
5574
0
        break;
5575
5576
0
    case CRAM_OPT_NTHREADS: {
5577
0
        int nthreads =  va_arg(args, int);
5578
0
        CHECK_RANGE(nthreads, 0, INT_MAX/2);
5579
0
        if (fd->pool)
5580
0
            return -2;  //already exists!
5581
0
        if (nthreads >= 1) {
5582
0
            if (!(fd->pool = hts_tpool_init(nthreads)))
5583
0
                return -1;
5584
5585
0
            fd->rqueue = hts_tpool_process_init(fd->pool, nthreads*2, 0);
5586
0
            fd->shared_ref = 1;
5587
0
            fd->own_pool = 1;
5588
0
        }
5589
0
        break;
5590
0
    }
5591
5592
0
    case CRAM_OPT_THREAD_POOL: {
5593
0
        htsThreadPool *p = va_arg(args, htsThreadPool *);
5594
0
        if (fd->pool)
5595
0
            return -2;  //already exists!
5596
0
        fd->pool = p ? p->pool : NULL;
5597
0
        if (fd->pool) {
5598
0
            fd->rqueue = hts_tpool_process_init(fd->pool,
5599
0
                                                p->qsize ? p->qsize : hts_tpool_size(fd->pool)*2,
5600
0
                                                0);
5601
0
        }
5602
0
        fd->shared_ref = 1; // Needed to avoid clobbering ref between threads
5603
0
        fd->own_pool = 0;
5604
5605
        //fd->qsize = 1;
5606
        //fd->decoded = calloc(fd->qsize, sizeof(cram_container *));
5607
        //hts_tpool_dispatch(fd->pool, cram_decoder_thread, fd);
5608
0
        break;
5609
0
    }
5610
5611
0
    case CRAM_OPT_REQUIRED_FIELDS:
5612
0
        CHECK_RANGE(fd->required_fields = va_arg(args, int), 0, SAM_RGAUX*2-1);
5613
0
        if (fd->range.refid != -2)
5614
0
            fd->required_fields |= SAM_POS;
5615
0
        break;
5616
5617
0
    case CRAM_OPT_STORE_MD:
5618
0
        CHECK_RANGE(fd->store_md = va_arg(args, int), 0, 1);
5619
0
        break;
5620
5621
0
    case CRAM_OPT_STORE_NM:
5622
0
        CHECK_RANGE(fd->store_nm = va_arg(args, int), 0, 1);
5623
0
        break;
5624
5625
0
    case CRAM_OPT_RM_UR:
5626
0
        CHECK_RANGE(fd->remove_ur = va_arg(args, int), 0, 1);
5627
0
        break;
5628
5629
0
    case HTS_OPT_COMPRESSION_LEVEL:
5630
0
        CHECK_RANGE(fd->level = va_arg(args, int), -1, INT_MAX);
5631
0
        break;
5632
5633
0
    case HTS_OPT_PROFILE: {
5634
0
        enum hts_profile_option prof = va_arg(args, int);
5635
0
        switch (prof) {
5636
0
        case HTS_PROFILE_FAST:
5637
0
            if (fd->level == CRAM_DEFAULT_LEVEL) fd->level = 1;
5638
0
            fd->use_tok = 0;
5639
0
            fd->seqs_per_slice = 10000;
5640
0
            break;
5641
5642
0
        case HTS_PROFILE_NORMAL:
5643
0
            break;
5644
5645
0
        case HTS_PROFILE_SMALL:
5646
0
            if (fd->level == CRAM_DEFAULT_LEVEL) fd->level = 6;
5647
0
            fd->use_bz2 = 1;
5648
0
            fd->use_fqz = 1;
5649
0
            fd->seqs_per_slice = 25000;
5650
0
            break;
5651
5652
0
        case HTS_PROFILE_ARCHIVE:
5653
0
            if (fd->level == CRAM_DEFAULT_LEVEL) fd->level = 7;
5654
0
            fd->use_bz2 = 1;
5655
0
            fd->use_fqz = 1;
5656
0
            fd->use_arith = 1;
5657
0
            if (fd->level > 7)
5658
0
                fd->use_lzma = 1;
5659
0
            fd->seqs_per_slice = 100000;
5660
0
            break;
5661
0
        }
5662
5663
0
        if (fd->bases_per_slice == BASES_PER_SLICE)
5664
0
            fd->bases_per_slice = fd->seqs_per_slice * 500;
5665
0
        break;
5666
0
    }
5667
5668
0
    default:
5669
0
        hts_log_error("Unknown CRAM option code %d", opt);
5670
0
        errno = EINVAL;
5671
0
        return -1;
5672
9.45k
    }
5673
5674
0
    return 0;
5675
9.45k
}
5676
5677
int cram_check_EOF(cram_fd *fd)
5678
0
{
5679
    // Byte 9 in these templates is & with 0x0f to resolve differences
5680
    // between ITF-8 interpretations between early Java and C
5681
    // implementations of CRAM
5682
0
    static const unsigned char TEMPLATE_2_1[30] = {
5683
0
        0x0b, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x0f, 0xe0,
5684
0
        0x45, 0x4f, 0x46, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
5685
0
        0x01, 0x00, 0x06, 0x06, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00
5686
0
    };
5687
0
    static const unsigned char TEMPLATE_3[38] = {
5688
0
        0x0f, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x0f, 0xe0,
5689
0
        0x45, 0x4f, 0x46, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x05,
5690
0
        0xbd, 0xd9, 0x4f, 0x00, 0x01, 0x00, 0x06, 0x06, 0x01, 0x00,
5691
0
        0x01, 0x00, 0x01, 0x00, 0xee, 0x63, 0x01, 0x4b
5692
0
    };
5693
5694
0
    unsigned char buf[38]; // max(sizeof TEMPLATE_*)
5695
5696
0
    uint8_t major = CRAM_MAJOR_VERS(fd->version);
5697
0
    uint8_t minor = CRAM_MINOR_VERS(fd->version);
5698
5699
0
    const unsigned char *template;
5700
0
    ssize_t template_len;
5701
0
    if ((major < 2) ||
5702
0
        (major == 2 && minor == 0)) {
5703
0
        return 3; // No EOF support in cram versions less than 2.1
5704
0
    } else if (major == 2 && minor == 1) {
5705
0
        template = TEMPLATE_2_1;
5706
0
        template_len = sizeof TEMPLATE_2_1;
5707
0
    } else {
5708
0
        template = TEMPLATE_3;
5709
0
        template_len = sizeof TEMPLATE_3;
5710
0
    }
5711
5712
0
    off_t offset = htell(fd->fp);
5713
0
    if (hseek(fd->fp, -template_len, SEEK_END) < 0) {
5714
0
        if (errno == ESPIPE) {
5715
0
            hclearerr(fd->fp);
5716
0
            return 2;
5717
0
        }
5718
0
        else {
5719
0
            return -1;
5720
0
        }
5721
0
    }
5722
0
    if (hread(fd->fp, buf, template_len) != template_len) return -1;
5723
0
    if (hseek(fd->fp, offset, SEEK_SET) < 0) return -1;
5724
0
    buf[8] &= 0x0f;
5725
0
    return (memcmp(template, buf, template_len) == 0)? 1 : 0;
5726
0
}