Coverage Report

Created: 2026-10-17 06:30

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
940k
#define TRIAL_SPAN 70
119
940k
#define NTRIALS 3
120
121
18.1k
#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
277k
int itf8_decode_crc(cram_fd *fd, int32_t *val_p, uint32_t *crc) {
197
277k
    static int nbytes[16] = {
198
277k
        0,0,0,0, 0,0,0,0,                               // 0000xxxx - 0111xxxx
199
277k
        1,1,1,1,                                        // 1000xxxx - 1011xxxx
200
277k
        2,2,                                            // 1100xxxx - 1101xxxx
201
277k
        3,                                              // 1110xxxx
202
277k
        4,                                              // 1111xxxx
203
277k
    };
204
205
277k
    static int nbits[16] = {
206
277k
        0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, // 0000xxxx - 0111xxxx
207
277k
        0x3f, 0x3f, 0x3f, 0x3f,                         // 1000xxxx - 1011xxxx
208
277k
        0x1f, 0x1f,                                     // 1100xxxx - 1101xxxx
209
277k
        0x0f,                                           // 1110xxxx
210
277k
        0x0f,                                           // 1111xxxx
211
277k
    };
212
277k
    unsigned char c[5];
213
214
277k
    int32_t val = hgetc(fd->fp);
215
277k
    if (val == -1)
216
350
        return -1;
217
218
276k
    c[0]=val;
219
220
276k
    int i = nbytes[val>>4];
221
276k
    val &= nbits[val>>4];
222
223
276k
    if (i > 0) {
224
37.9k
        if (hread(fd->fp, &c[1], i) < i)
225
104
            return -1;
226
37.9k
    }
227
228
276k
    switch(i) {
229
238k
    case 0:
230
238k
        *val_p = val;
231
238k
        *crc = crc32(*crc, c, 1);
232
238k
        return 1;
233
234
6.61k
    case 1:
235
6.61k
        val = (val<<8) | c[1];
236
6.61k
        *val_p = val;
237
6.61k
        *crc = crc32(*crc, c, 2);
238
6.61k
        return 2;
239
240
24.2k
    case 2:
241
24.2k
        val = (val<<8) | c[1];
242
24.2k
        val = (val<<8) | c[2];
243
24.2k
        *val_p = val;
244
24.2k
        *crc = crc32(*crc, c, 3);
245
24.2k
        return 3;
246
247
1.56k
    case 3:
248
1.56k
        val = (val<<8) | c[1];
249
1.56k
        val = (val<<8) | c[2];
250
1.56k
        val = (val<<8) | c[3];
251
1.56k
        *val_p = val;
252
1.56k
        *crc = crc32(*crc, c, 4);
253
1.56k
        return 4;
254
255
5.37k
    case 4: // really 3.5 more, why make it different?
256
5.37k
        {
257
5.37k
            uint32_t uv = val;
258
5.37k
            uv = (uv<<8) |  c[1];
259
5.37k
            uv = (uv<<8) |  c[2];
260
5.37k
            uv = (uv<<8) |  c[3];
261
5.37k
            uv = (uv<<4) | (c[4] & 0x0f);
262
            // Avoid implementation-defined behaviour on negative values
263
5.37k
            *val_p = uv < 0x80000000UL ? (int32_t) uv : -((int32_t) (0xffffffffUL - uv)) - 1;
264
5.37k
            *crc = crc32(*crc, c, 5);
265
5.37k
        }
266
276k
    }
267
268
5.37k
    return 5;
269
276k
}
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
19.8M
static inline int itf8_put(char *cp, int32_t val) {
278
19.8M
    unsigned char *up = (unsigned char *)cp;
279
19.8M
    if        (!(val & ~0x00000007f)) { // 1 byte
280
18.7M
        *up = val;
281
18.7M
        return 1;
282
18.7M
    } else if (!(val & ~0x00003fff)) { // 2 byte
283
531k
        *up++ = (val >> 8 ) | 0x80;
284
531k
        *up   = val & 0xff;
285
531k
        return 2;
286
660k
    } else if (!(val & ~0x01fffff)) { // 3 byte
287
10.1k
        *up++ = (val >> 16) | 0xc0;
288
10.1k
        *up++ = (val >> 8 ) & 0xff;
289
10.1k
        *up   = val & 0xff;
290
10.1k
        return 3;
291
650k
    } else if (!(val & ~0x0fffffff)) { // 4 byte
292
454k
        *up++ = (val >> 24) | 0xe0;
293
454k
        *up++ = (val >> 16) & 0xff;
294
454k
        *up++ = (val >> 8 ) & 0xff;
295
454k
        *up   = val & 0xff;
296
454k
        return 4;
297
454k
    } else {                           // 5 byte
298
195k
        *up++ = 0xf0 | ((val>>28) & 0xff);
299
195k
        *up++ = (val >> 20) & 0xff;
300
195k
        *up++ = (val >> 12) & 0xff;
301
195k
        *up++ = (val >> 4 ) & 0xff;
302
195k
        *up = val & 0x0f;
303
195k
        return 5;
304
195k
    }
305
19.8M
}
306
307
308
/* 64-bit itf8 variant */
309
150k
static inline int ltf8_put(char *cp, int64_t val) {
310
150k
    unsigned char *up = (unsigned char *)cp;
311
150k
    if        (!(val & ~((1LL<<7)-1))) {
312
105k
        *up = val;
313
105k
        return 1;
314
105k
    } else if (!(val & ~((1LL<<(6+8))-1))) {
315
43.6k
        *up++ = (val >> 8 ) | 0x80;
316
43.6k
        *up   = val & 0xff;
317
43.6k
        return 2;
318
43.6k
    } else if (!(val & ~((1LL<<(5+2*8))-1))) {
319
1.14k
        *up++ = (val >> 16) | 0xc0;
320
1.14k
        *up++ = (val >> 8 ) & 0xff;
321
1.14k
        *up   = val & 0xff;
322
1.14k
        return 3;
323
1.14k
    } else if (!(val & ~((1LL<<(4+3*8))-1))) {
324
68
        *up++ = (val >> 24) | 0xe0;
325
68
        *up++ = (val >> 16) & 0xff;
326
68
        *up++ = (val >> 8 ) & 0xff;
327
68
        *up   = val & 0xff;
328
68
        return 4;
329
68
    } 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
150k
}
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
21.6k
int ltf8_decode_crc(cram_fd *fd, int64_t *val_p, uint32_t *crc) {
502
21.6k
    unsigned char c[9];
503
21.6k
    int64_t val = hgetc(fd->fp);
504
21.6k
    if (val < 0)
505
18
        return -1;
506
507
21.6k
    c[0] = val;
508
509
21.6k
    if (val < 0x80) {
510
19.8k
        *val_p =   val;
511
19.8k
        *crc = crc32(*crc, c, 1);
512
19.8k
        return 1;
513
514
19.8k
    } else if (val < 0xc0) {
515
381
        int v = hgetc(fd->fp);
516
381
        if (v < 0)
517
8
            return -1;
518
373
        val = (val<<8) | (c[1]=v);
519
373
        *val_p = val & (((1LL<<(6+8)))-1);
520
373
        *crc = crc32(*crc, c, 2);
521
373
        return 2;
522
523
1.45k
    } else if (val < 0xe0) {
524
420
        if (hread(fd->fp, &c[1], 2) < 2)
525
7
            return -1;
526
413
        val = (val<<8) | c[1];
527
413
        val = (val<<8) | c[2];
528
413
        *val_p = val & ((1LL<<(5+2*8))-1);
529
413
        *crc = crc32(*crc, c, 3);
530
413
        return 3;
531
532
1.03k
    } else if (val < 0xf0) {
533
386
        if (hread(fd->fp, &c[1], 3) < 3)
534
4
            return -1;
535
382
        val = (val<<8) | c[1];
536
382
        val = (val<<8) | c[2];
537
382
        val = (val<<8) | c[3];
538
382
        *val_p = val & ((1LL<<(4+3*8))-1);
539
382
        *crc = crc32(*crc, c, 4);
540
382
        return 4;
541
542
651
    } else if (val < 0xf8) {
543
41
        if (hread(fd->fp, &c[1], 4) < 4)
544
4
            return -1;
545
37
        val = (val<<8) | c[1];
546
37
        val = (val<<8) | c[2];
547
37
        val = (val<<8) | c[3];
548
37
        val = (val<<8) | c[4];
549
37
        *val_p = val & ((1LL<<(3+4*8))-1);
550
37
        *crc = crc32(*crc, c, 5);
551
37
        return 5;
552
553
610
    } else if (val < 0xfc) {
554
54
        if (hread(fd->fp, &c[1], 5) < 5)
555
3
            return -1;
556
51
        val = (val<<8) | c[1];
557
51
        val = (val<<8) | c[2];
558
51
        val = (val<<8) | c[3];
559
51
        val = (val<<8) | c[4];
560
51
        val = (val<<8) | c[5];
561
51
        *val_p = val & ((1LL<<(2+5*8))-1);
562
51
        *crc = crc32(*crc, c, 6);
563
51
        return 6;
564
565
556
    } else if (val < 0xfe) {
566
58
        if (hread(fd->fp, &c[1], 6) < 6)
567
4
            return -1;
568
54
        val = (val<<8) | c[1];
569
54
        val = (val<<8) | c[2];
570
54
        val = (val<<8) | c[3];
571
54
        val = (val<<8) | c[4];
572
54
        val = (val<<8) | c[5];
573
54
        val = (val<<8) | c[6];
574
54
        *val_p = val & ((1LL<<(1+6*8))-1);
575
54
        *crc = crc32(*crc, c, 7);
576
54
        return 7;
577
578
498
    } else if (val < 0xff) {
579
39
        uint64_t uval = val;
580
39
        if (hread(fd->fp, &c[1], 7) < 7)
581
9
            return -1;
582
30
        uval = (uval<<8) | c[1];
583
30
        uval = (uval<<8) | c[2];
584
30
        uval = (uval<<8) | c[3];
585
30
        uval = (uval<<8) | c[4];
586
30
        uval = (uval<<8) | c[5];
587
30
        uval = (uval<<8) | c[6];
588
30
        uval = (uval<<8) | c[7];
589
30
        *val_p = uval & ((1ULL<<(7*8))-1);
590
30
        *crc = crc32(*crc, c, 8);
591
30
        return 8;
592
593
459
    } else {
594
459
        uint64_t uval;
595
459
        if (hread(fd->fp, &c[1], 8) < 8)
596
4
            return -1;
597
455
        uval =             c[1];
598
455
        uval = (uval<<8) | c[2];
599
455
        uval = (uval<<8) | c[3];
600
455
        uval = (uval<<8) | c[4];
601
455
        uval = (uval<<8) | c[5];
602
455
        uval = (uval<<8) | c[6];
603
455
        uval = (uval<<8) | c[7];
604
455
        uval = (uval<<8) | c[8];
605
455
        *crc = crc32(*crc, c, 9);
606
        // Avoid implementation-defined behaviour on negative values
607
455
        *val_p = c[1] < 0x80 ? (int64_t) uval : -((int64_t) (0xffffffffffffffffULL - uval)) - 1;
608
455
    }
609
610
455
    return 9;
611
21.6k
}
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
13.9M
int itf8_put_blk(cram_block *blk, int32_t val) {
621
13.9M
    char buf[5];
622
13.9M
    int sz;
623
624
13.9M
    sz = itf8_put(buf, val);
625
13.9M
    BLOCK_APPEND(blk, buf, sz);
626
13.9M
    return sz;
627
628
0
 block_err:
629
0
    return -1;
630
13.9M
}
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
305k
static int64_t safe_itf8_get(char **cp, const char *endp, int *err) {
645
305k
    const unsigned char *up = (unsigned char *)*cp;
646
647
305k
    if (endp && endp - *cp < 5 &&
648
133k
        (*cp >= endp || endp - *cp < itf8_bytes[up[0]>>4])) {
649
129k
        if (err) *err = 1;
650
129k
        return 0;
651
129k
    }
652
653
175k
    if (up[0] < 0x80) {
654
159k
        (*cp)++;
655
159k
        return up[0];
656
159k
    } else if (up[0] < 0xc0) {
657
6.80k
        (*cp)+=2;
658
6.80k
        return ((up[0] <<8) |  up[1])                           & 0x3fff;
659
9.31k
    } else if (up[0] < 0xe0) {
660
2.12k
        (*cp)+=3;
661
2.12k
        return ((up[0]<<16) | (up[1]<< 8) |  up[2])             & 0x1fffff;
662
7.19k
    } else if (up[0] < 0xf0) {
663
1.80k
        (*cp)+=4;
664
1.80k
        uint32_t uv = (((uint32_t)up[0]<<24) | (up[1]<<16) | (up[2]<<8) | up[3]) & 0x0fffffff;
665
1.80k
        return (int32_t)uv;
666
5.38k
    } else {
667
5.38k
        (*cp)+=5;
668
5.38k
        uint32_t uv = (((uint32_t)up[0] & 0x0f)<<28) | (up[1]<<20) | (up[2]<<12) | (up[3]<<4) | (up[4] & 0x0f);
669
5.38k
        return (int32_t)uv;
670
5.38k
    }
671
175k
}
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.95M
static int safe_itf8_put(char *cp, char *cp_end, int32_t val) {
748
5.95M
    return itf8_put(cp, val);
749
5.95M
}
750
751
150k
static int safe_ltf8_put(char *cp, char *cp_end, int64_t val) {
752
150k
    return ltf8_put(cp, val);
753
150k
}
754
755
1.41M
static int itf8_size(int64_t v) {
756
1.41M
    return ((!((v)&~0x7f))?1:(!((v)&~0x3fff))?2:(!((v)&~0x1fffff))?3:(!((v)&~0xfffffff))?4:5);
757
1.41M
}
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
22.2k
static int int32_decode(cram_fd *fd, int32_t *val) {
768
22.2k
    int32_t i;
769
22.2k
    if (4 != hread(fd->fp, &i, 4))
770
42
        return -1;
771
772
22.2k
    *val = le_int4(i);
773
22.2k
    return 4;
774
22.2k
}
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
376k
static int int32_encode(cram_fd *fd, int32_t val) {
783
376k
    uint32_t v = le_int4(val);
784
376k
    if (4 != hwrite(fd->fp, &v, 4))
785
0
        return -1;
786
787
376k
    return 4;
788
376k
}
789
790
/* As int32_decoded/encode, but from/to blocks instead of cram_fd */
791
358
int int32_get_blk(cram_block *b, int32_t *val) {
792
358
    if (b->uncomp_size - BLOCK_SIZE(b) < 4)
793
56
        return -1;
794
795
302
    uint32_t v =
796
302
         ((uint32_t) b->data[b->byte  ])        |
797
302
        (((uint32_t) b->data[b->byte+1]) <<  8) |
798
302
        (((uint32_t) b->data[b->byte+2]) << 16) |
799
302
        (((uint32_t) b->data[b->byte+3]) << 24);
800
    // Avoid implementation-defined behaviour on negative values
801
302
    *val = v < 0x80000000U ? (int32_t) v : -((int32_t) (0xffffffffU - v)) - 1;
802
302
    BLOCK_SIZE(b) += 4;
803
302
    return 4;
804
358
}
805
806
/* As int32_decoded/encode, but from/to blocks instead of cram_fd */
807
7.98k
int int32_put_blk(cram_block *b, int32_t val) {
808
7.98k
    unsigned char cp[4];
809
7.98k
    uint32_t v = val;
810
7.98k
    cp[0] = ( v      & 0xff);
811
7.98k
    cp[1] = ((v>>8)  & 0xff);
812
7.98k
    cp[2] = ((v>>16) & 0xff);
813
7.98k
    cp[3] = ((v>>24) & 0xff);
814
815
7.98k
    BLOCK_APPEND(b, cp, 4);
816
7.98k
    return 0;
817
818
0
 block_err:
819
0
    return -1;
820
7.98k
}
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
12
char *zlib_mem_inflate(char *cdata, size_t csize, size_t *size) {
907
12
    z_stream s;
908
12
    unsigned char *data = NULL; /* Uncompressed output */
909
12
    int err;
910
911
12
    assert(*size > 0);
912
    // These should always be true due to type of cram_block::comp_size
913
    // and cram_block::uncomp_size
914
12
    assert(*size < UINT_MAX);
915
12
    assert(csize < UINT_MAX);
916
12
    data = malloc(*size);
917
12
    if (!data)
918
0
        return NULL;
919
920
    /* Initialise zlib stream */
921
12
    s.zalloc = Z_NULL; /* use default allocation functions */
922
12
    s.zfree  = Z_NULL;
923
12
    s.msg    = Z_NULL;
924
12
    s.opaque = Z_NULL;
925
12
    s.next_in  = (unsigned char *)cdata;
926
12
    s.avail_in = (uInt) csize;
927
12
    s.total_in = 0;
928
12
    s.next_out  = data;
929
12
    s.avail_out = (uInt) *size;
930
12
    s.total_out = 0;
931
932
    //err = inflateInit(&s);
933
12
    err = inflateInit2(&s, 15 + 32);
934
12
    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
12
    err = inflate(&s, Z_FINISH);
942
943
12
    if (err != Z_STREAM_END) {
944
12
        hts_log_error("Call to zlib inflate failed: %s",
945
12
                      err != Z_OK ? s.msg : "not enough data");
946
12
        free(data);
947
12
        inflateEnd(&s);
948
12
        return NULL;
949
12
    }
950
951
0
    inflateEnd(&s);
952
953
0
    *size = s.total_out;
954
0
    return (char *)data;
955
12
}
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
325k
                              int level, int strat) {
961
325k
    z_stream s;
962
325k
    unsigned char *cdata = NULL; /* Compressed output */
963
325k
    int cdata_alloc = 0;
964
325k
    int cdata_pos = 0;
965
325k
    int err;
966
967
325k
    cdata = malloc(cdata_alloc = size*1.05+100);
968
325k
    if (!cdata)
969
0
        return NULL;
970
325k
    cdata_pos = 0;
971
972
    /* Initialise zlib stream */
973
325k
    s.zalloc = Z_NULL; /* use default allocation functions */
974
325k
    s.zfree  = Z_NULL;
975
325k
    s.opaque = Z_NULL;
976
325k
    s.next_in  = (unsigned char *)data;
977
325k
    s.avail_in = size;
978
325k
    s.total_in = 0;
979
325k
    s.next_out  = cdata;
980
325k
    s.avail_out = cdata_alloc;
981
325k
    s.total_out = 0;
982
325k
    s.data_type = Z_BINARY;
983
984
325k
    err = deflateInit2(&s, level, Z_DEFLATED, 15|16, 9, strat);
985
325k
    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
650k
    for (;s.avail_in;) {
992
325k
        s.next_out = &cdata[cdata_pos];
993
325k
        s.avail_out = cdata_alloc - cdata_pos;
994
325k
        if (cdata_alloc - cdata_pos <= 0) {
995
0
            hts_log_error("Deflate produced larger output than expected");
996
0
            return NULL;
997
0
        }
998
325k
        err = deflate(&s, Z_NO_FLUSH);
999
325k
        cdata_pos = cdata_alloc - s.avail_out;
1000
325k
        if (err != Z_OK) {
1001
0
            hts_log_error("Call to zlib deflate failed: %s", s.msg);
1002
0
            break;
1003
0
        }
1004
325k
    }
1005
325k
    if (deflate(&s, Z_FINISH) != Z_STREAM_END) {
1006
0
        hts_log_error("Call to zlib deflate failed: %s", s.msg);
1007
0
    }
1008
325k
    *cdata_size = s.total_out;
1009
1010
325k
    if (deflateEnd(&s) != Z_OK) {
1011
0
        hts_log_error("Call to zlib deflate failed: %s", s.msg);
1012
0
    }
1013
325k
    return (char *)cdata;
1014
325k
}
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
1.00M
                           int content_id) {
1127
1.00M
    cram_block *b = malloc(sizeof(*b));
1128
1.00M
    if (!b)
1129
0
        return NULL;
1130
1.00M
    b->method = b->orig_method = RAW;
1131
1.00M
    b->content_type = content_type;
1132
1.00M
    b->content_id = content_id;
1133
1.00M
    b->comp_size = 0;
1134
1.00M
    b->uncomp_size = 0;
1135
1.00M
    b->data = NULL;
1136
1.00M
    b->alloc = 0;
1137
1.00M
    b->byte = 0;
1138
1.00M
    b->bit = 7; // MSB
1139
1.00M
    b->crc32 = 0;
1140
1.00M
    b->idx = 0;
1141
1.00M
    b->m = NULL;
1142
1143
1.00M
    return b;
1144
1.00M
}
1145
1146
/*
1147
 * Reads a block from a cram file.
1148
 * Returns cram_block pointer on success.
1149
 *         NULL on failure
1150
 */
1151
10.3k
cram_block *cram_read_block(cram_fd *fd) {
1152
10.3k
    cram_block *b = malloc(sizeof(*b));
1153
10.3k
    unsigned char c;
1154
10.3k
    uint32_t crc = 0;
1155
10.3k
    if (!b)
1156
0
        return NULL;
1157
1158
    //fprintf(stderr, "Block at %d\n", (int)ftell(fd->fp));
1159
1160
10.3k
    if (-1 == (b->method      = hgetc(fd->fp))) { free(b); return NULL; }
1161
10.3k
    if (b->method > TOK3) {
1162
117
        hts_log_error("Unknown block compression method %d", (int) b->method);
1163
117
        free(b); return NULL;
1164
117
    }
1165
10.2k
    c = b->method; crc = crc32(crc, &c, 1);
1166
10.2k
    if (-1 == (b->content_type= hgetc(fd->fp))) { free(b); return NULL; }
1167
10.1k
    c = b->content_type; crc = crc32(crc, &c, 1);
1168
10.1k
    if (-1 == fd->vv.varint_decode32_crc(fd, &b->content_id, &crc))  { free(b); return NULL; }
1169
10.1k
    if (-1 == fd->vv.varint_decode32_crc(fd, &b->comp_size, &crc))   { free(b); return NULL; }
1170
10.1k
    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.1k
    if (b->method == RAW) {
1176
3.60k
        if (b->uncomp_size < 0 || b->comp_size != b->uncomp_size) {
1177
90
            free(b);
1178
90
            return NULL;
1179
90
        }
1180
3.51k
        b->alloc = b->uncomp_size;
1181
3.51k
        if (!(b->data = malloc(b->uncomp_size))){ free(b); return NULL; }
1182
3.51k
        if (b->uncomp_size != hread(fd->fp, b->data, b->uncomp_size)) {
1183
16
            free(b->data);
1184
16
            free(b);
1185
16
            return NULL;
1186
16
        }
1187
6.52k
    } else {
1188
6.52k
        if (b->comp_size < 0 || b->uncomp_size < 0) {
1189
46
            free(b);
1190
46
            return NULL;
1191
46
        }
1192
6.47k
        b->alloc = b->comp_size;
1193
6.47k
        if (!(b->data = malloc(b->comp_size)))  { free(b); return NULL; }
1194
6.47k
        if (b->comp_size != hread(fd->fp, b->data, b->comp_size)) {
1195
22
            free(b->data);
1196
22
            free(b);
1197
22
            return NULL;
1198
22
        }
1199
6.47k
    }
1200
1201
9.95k
    if (CRAM_MAJOR_VERS(fd->version) >= 3) {
1202
344
        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
339
        b->crc32_checked = fd->ignore_md5;
1209
339
        b->crc_part = crc;
1210
9.61k
    } else {
1211
9.61k
        b->crc32_checked = 1; // CRC not present
1212
9.61k
    }
1213
1214
9.95k
    b->orig_method = b->method;
1215
9.95k
    b->idx = 0;
1216
9.95k
    b->byte = 0;
1217
9.95k
    b->bit = 7; // MSB
1218
1219
9.95k
    return b;
1220
9.95k
}
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
376k
int cram_write_block(cram_fd *fd, cram_block *b) {
1249
376k
    char vardata[100];
1250
376k
    int vardata_o = 0;
1251
1252
376k
    assert(b->method != RAW || (b->comp_size == b->uncomp_size));
1253
1254
376k
    if (hputc(b->method,       fd->fp)  == EOF) return -1;
1255
376k
    if (hputc(b->content_type, fd->fp)  == EOF) return -1;
1256
376k
    vardata_o += fd->vv.varint_put32(vardata          , vardata+100, b->content_id);
1257
376k
    vardata_o += fd->vv.varint_put32(vardata+vardata_o, vardata+100, b->comp_size);
1258
376k
    vardata_o += fd->vv.varint_put32(vardata+vardata_o, vardata+100, b->uncomp_size);
1259
376k
    if (vardata_o != hwrite(fd->fp, vardata, vardata_o))
1260
0
        return -1;
1261
1262
376k
    if (b->data) {
1263
338k
        if (b->method == RAW) {
1264
279k
            if (b->uncomp_size != hwrite(fd->fp, b->data, b->uncomp_size))
1265
0
                return -1;
1266
279k
        } else {
1267
59.3k
            if (b->comp_size != hwrite(fd->fp, b->data, b->comp_size))
1268
0
                return -1;
1269
59.3k
        }
1270
338k
    } else {
1271
        // Absent blocks should be size 0
1272
38.0k
        assert(b->method == RAW && b->uncomp_size == 0);
1273
38.0k
    }
1274
1275
376k
    if (CRAM_MAJOR_VERS(fd->version) >= 3) {
1276
376k
        char dat[100], *cp = (char *)dat;
1277
376k
        uint32_t crc;
1278
1279
376k
        *cp++ = b->method;
1280
376k
        *cp++ = b->content_type;
1281
376k
        cp += fd->vv.varint_put32(cp, dat+100, b->content_id);
1282
376k
        cp += fd->vv.varint_put32(cp, dat+100, b->comp_size);
1283
376k
        cp += fd->vv.varint_put32(cp, dat+100, b->uncomp_size);
1284
376k
        crc = crc32(0L, (uc *)dat, cp-dat);
1285
1286
376k
        if (b->method == RAW) {
1287
317k
            b->crc32 = crc32(crc, b->data ? b->data : (uc*)"", b->uncomp_size);
1288
317k
        } else {
1289
59.3k
            b->crc32 = crc32(crc, b->data ? b->data : (uc*)"", b->comp_size);
1290
59.3k
        }
1291
1292
376k
        if (-1 == int32_encode(fd, b->crc32))
1293
0
            return -1;
1294
376k
    }
1295
1296
376k
    return 0;
1297
376k
}
1298
1299
/*
1300
 * Frees a CRAM block, deallocating internal data too.
1301
 */
1302
1.31M
void cram_free_block(cram_block *b) {
1303
1.31M
    if (!b)
1304
297k
        return;
1305
1.01M
    if (b->data)
1306
657k
        free(b->data);
1307
1.01M
    free(b);
1308
1.01M
}
1309
1310
/*
1311
 * Uncompresses a CRAM block, if compressed.
1312
 */
1313
6.59k
int cram_uncompress_block(cram_block *b) {
1314
6.59k
    char *uncomp;
1315
6.59k
    size_t uncomp_size = 0;
1316
1317
6.59k
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
1318
    // Pretend the CRC was OK so the fuzzer doesn't have to get it right
1319
6.59k
    b->crc32_checked = 1;
1320
6.59k
#endif
1321
1322
6.59k
    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
6.59k
    if (b->uncomp_size == 0) {
1332
        // blank block
1333
568
        b->method = RAW;
1334
568
        return 0;
1335
568
    }
1336
6.59k
    assert(b->uncomp_size >= 0); // cram_read_block should ensure this
1337
1338
6.02k
    switch (b->method) {
1339
301
    case RAW:
1340
301
        return 0;
1341
1342
20
    case GZIP:
1343
20
        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
8
            hts_log_error("GZIP cram block has impossibly large compression ratio");
1348
8
            return -1;
1349
8
        }
1350
12
        uncomp_size = b->uncomp_size;
1351
12
        uncomp = zlib_mem_inflate((char *)b->data, b->comp_size, &uncomp_size);
1352
1353
12
        if (!uncomp)
1354
12
            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
491
    case RANS: {
1411
491
        unsigned int usize = b->uncomp_size, usize2 = 0;
1412
491
        uncomp = (char *)rans_uncompress(b->data, b->comp_size, &usize2);
1413
491
        if (!uncomp)
1414
255
            return -1;
1415
236
        if (usize != usize2) {
1416
218
            free(uncomp);
1417
218
            return -1;
1418
218
        }
1419
18
        free(b->data);
1420
18
        b->data = (unsigned char *)uncomp;
1421
18
        b->alloc = usize2;
1422
18
        b->method = RAW;
1423
18
        b->uncomp_size = usize2; // Just in case it differs
1424
        //fprintf(stderr, "Expanded %d to %d\n", b->comp_size, b->uncomp_size);
1425
18
        break;
1426
236
    }
1427
1428
823
    case FQZ: {
1429
823
        uncomp_size = b->uncomp_size;
1430
823
        uncomp = fqz_decompress((char *)b->data, b->comp_size, &uncomp_size, NULL, 0);
1431
823
        if (!uncomp)
1432
612
            return -1;
1433
211
        free(b->data);
1434
211
        b->data = (unsigned char *)uncomp;
1435
211
        b->alloc = uncomp_size;
1436
211
        b->method = RAW;
1437
211
        b->uncomp_size = uncomp_size;
1438
211
        break;
1439
823
    }
1440
1441
1.57k
    case RANS_PR0: {
1442
1.57k
        unsigned int usize = b->uncomp_size, usize2 = 0;
1443
1.57k
        uncomp = (char *)rans_uncompress_4x16(b->data, b->comp_size, &usize2);
1444
1.57k
        if (!uncomp)
1445
818
            return -1;
1446
752
        if (usize != usize2) {
1447
159
            free(uncomp);
1448
159
            return -1;
1449
159
        }
1450
593
        b->orig_method = RANSPR;
1451
593
        free(b->data);
1452
593
        b->data = (unsigned char *)uncomp;
1453
593
        b->alloc = usize2;
1454
593
        b->method = RAW;
1455
593
        b->uncomp_size = usize2; // Just in case it differs
1456
        //fprintf(stderr, "Expanded %d to %d\n", b->comp_size, b->uncomp_size);
1457
593
        break;
1458
752
    }
1459
1460
608
    case ARITH_PR0: {
1461
608
        unsigned int usize = b->uncomp_size, usize2 = 0;
1462
608
        uncomp = (char *)arith_uncompress_to(b->data, b->comp_size, NULL, &usize2);
1463
608
        if (!uncomp)
1464
373
            return -1;
1465
235
        if (usize != usize2) {
1466
60
            free(uncomp);
1467
60
            return -1;
1468
60
        }
1469
175
        b->orig_method = ARITH;
1470
175
        free(b->data);
1471
175
        b->data = (unsigned char *)uncomp;
1472
175
        b->alloc = usize2;
1473
175
        b->method = RAW;
1474
175
        b->uncomp_size = usize2; // Just in case it differs
1475
        //fprintf(stderr, "Expanded %d to %d\n", b->comp_size, b->uncomp_size);
1476
175
        break;
1477
235
    }
1478
1479
2.19k
    case TOK3: {
1480
2.19k
        uint32_t out_len;
1481
2.19k
        uint8_t *cp = tok3_decode_names(b->data, b->comp_size, &out_len);
1482
2.19k
        if (!cp)
1483
2.07k
            return -1;
1484
122
        b->orig_method = TOK3;
1485
122
        b->method = RAW;
1486
122
        free(b->data);
1487
122
        b->data = cp;
1488
122
        b->alloc = out_len;
1489
122
        b->uncomp_size = out_len;
1490
122
        break;
1491
2.19k
    }
1492
1493
0
    default:
1494
0
        return -1;
1495
6.02k
    }
1496
1497
1.11k
    return 0;
1498
6.02k
}
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
894k
                                     int level, int strat) {
1504
894k
    switch (method) {
1505
98.3k
    case GZIP:
1506
169k
    case GZIP_RLE:
1507
325k
    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
325k
        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
157k
    case RANS_PR0:
1589
228k
    case RANS_PR1:
1590
323k
    case RANS_PR64:
1591
393k
    case RANS_PR9:
1592
480k
    case RANS_PR128:
1593
480k
    case RANS_PR129:
1594
480k
    case RANS_PR192:
1595
551k
    case RANS_PR193: {
1596
551k
        unsigned int out_size_i;
1597
551k
        unsigned char *cp;
1598
1599
        // see enum cram_block. We map RANS_* methods to order bit-fields
1600
551k
        static int methmap[] = { 1, 64,9, 128,129, 192,193 };
1601
1602
551k
        int m = method == RANS_PR0 ? 0 : methmap[method - RANS_PR1];
1603
551k
        cp = rans_compress_4x16((unsigned char *)in, in_size, &out_size_i,
1604
551k
                                m | RANS_ORDER_SIMD_AUTO);
1605
551k
        *out_size = out_size_i;
1606
551k
        return (char *)cp;
1607
480k
    }
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
17.6k
    case TOK3:
1630
17.6k
    case TOKA: {
1631
17.6k
        int out_len;
1632
17.6k
        int lev = level;
1633
17.6k
        if (method == TOK3 && lev > 3)
1634
17.6k
            lev = 3;
1635
17.6k
        uint8_t *cp = tok3_encode_names(in, in_size, lev, strat, &out_len, NULL);
1636
17.6k
        *out_size = out_len;
1637
17.6k
        return (char *)cp;
1638
17.6k
    }
1639
1640
0
    case RAW:
1641
0
        break;
1642
1643
0
    default:
1644
0
        return NULL;
1645
894k
    }
1646
1647
0
    return NULL;
1648
894k
}
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
619k
                                int recurse) {
1660
1661
619k
    if (!b)
1662
37.6k
        return 0;
1663
1664
581k
    int orig_method = method;
1665
581k
    char *comp = NULL;
1666
581k
    size_t comp_size = 0;
1667
581k
    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
581k
    int methmap[] = {
1673
        // Externally defined values
1674
581k
        RAW, GZIP, BZIP2, LZMA, RANS, RANSPR, ARITH, FQZ, TOK3,
1675
1676
        // Reserved for possible expansion
1677
581k
        0, 0,
1678
1679
        // Internally parameterised versions matching back to above
1680
        // external values
1681
581k
        GZIP, GZIP,
1682
581k
        FQZ, FQZ, FQZ,
1683
581k
        RANS,
1684
581k
        RANSPR, RANSPR, RANSPR, RANSPR, RANSPR, RANSPR, RANSPR,
1685
581k
        TOK3,
1686
581k
        ARITH,  ARITH,  ARITH,  ARITH,  ARITH,  ARITH,  ARITH,
1687
581k
    };
1688
1689
581k
    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
581k
    if (method == -1) {
1699
7.98k
        method = 1<<GZIP;
1700
7.98k
        if (fd->use_bz2)
1701
0
            method |= 1<<BZIP2;
1702
7.98k
        if (fd->use_lzma)
1703
0
            method |= 1<<LZMA;
1704
7.98k
    }
1705
1706
581k
    if (level == -1)
1707
7.98k
        level = fd->level;
1708
1709
    //fprintf(stderr, "IN: block %d, sz %d\n", b->content_id, b->uncomp_size);
1710
1711
581k
    if (method == RAW || level == 0 || b->uncomp_size == 0) {
1712
286k
        b->method = RAW;
1713
286k
        b->comp_size = b->uncomp_size;
1714
        //fprintf(stderr, "Skip block id %d\n", b->content_id);
1715
286k
        return 0;
1716
286k
    }
1717
1718
295k
#ifndef ABS
1719
295k
#    define ABS(a) ((a)>=0?(a):-(a))
1720
295k
#endif
1721
1722
295k
    if (metrics) {
1723
285k
        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
285k
        if (metrics->input_avg_sz &&
1736
83.6k
            (b->uncomp_size/4 - 750 > metrics->input_avg_sz ||
1737
82.9k
             b->uncomp_size         < metrics->input_avg_sz/4 - 750) &&
1738
1.11k
            ABS(b->uncomp_size-metrics->input_avg_sz)/10
1739
1.11k
                > metrics->input_avg_delta) {
1740
107
            metrics->next_trial = 0;
1741
107
        }
1742
1743
285k
        if (metrics->trial > 0 || --metrics->next_trial <= 0) {
1744
88.4k
            int m, unpackable = metrics->unpackable;
1745
88.4k
            size_t sz_best = b->uncomp_size;
1746
88.4k
            size_t sz[CRAM_MAX_METHOD] = {0};
1747
88.4k
            int method_best = 0; // RAW
1748
88.4k
            char *c_best = NULL, *c = NULL;
1749
1750
88.4k
            metrics->input_avg_delta =
1751
88.4k
                0.9 * (metrics->input_avg_delta +
1752
88.4k
                       ABS(b->uncomp_size - metrics->input_avg_sz));
1753
1754
88.4k
            metrics->input_avg_sz += b->uncomp_size*.2;
1755
88.4k
            metrics->input_avg_sz *= 0.8;
1756
1757
88.4k
            if (metrics->revised_method)
1758
37.3k
                method = metrics->revised_method;
1759
51.0k
            else
1760
51.0k
                metrics->revised_method = method;
1761
1762
88.4k
            if (metrics->next_trial <= 0) {
1763
1.80k
                metrics->next_trial = TRIAL_SPAN;
1764
1.80k
                metrics->trial = NTRIALS;
1765
59.4k
                for (m = 0; m < CRAM_MAX_METHOD; m++)
1766
57.6k
                    metrics->sz[m] /= 2;
1767
1.80k
                metrics->unpackable = 0;
1768
1.80k
            }
1769
1770
            // Compress this block using the best method
1771
88.4k
            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
88.4k
            pthread_mutex_unlock(&fd->metrics_lock);
1801
1802
2.91M
            for (m = 0; m < CRAM_MAX_METHOD; m++) {
1803
2.82M
                if (method & (1u<<m)) {
1804
687k
                    int lvl = level;
1805
687k
                    switch (m) {
1806
87.8k
                    case GZIP:     strat = Z_FILTERED; break;
1807
88.3k
                    case GZIP_1:   strat = Z_DEFAULT_STRATEGY; lvl = 1; break;
1808
70.5k
                    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
17.4k
                    case TOK3:     strat = 0; break;
1814
0
                    case TOKA:     strat = 1; break;
1815
423k
                    default:       strat = 0;
1816
687k
                    }
1817
1818
687k
                    c = cram_compress_by_method(s, (char *)b->data, b->uncomp_size,
1819
687k
                                                b->content_id, &sz[m], m, lvl, strat);
1820
1821
687k
                    if (c && sz_best > sz[m]) {
1822
52.5k
                        sz_best = sz[m];
1823
52.5k
                        method_best = m;
1824
52.5k
                        if (c_best)
1825
26.0k
                            free(c_best);
1826
52.5k
                        c_best = c;
1827
634k
                    } else if (c) {
1828
633k
                        free(c);
1829
633k
                    } else {
1830
1.55k
                        sz[m] = UINT_MAX; // arbitrarily worse than raw
1831
1.55k
                    }
1832
2.14M
                } else {
1833
2.14M
                    sz[m] = UINT_MAX; // arbitrarily worse than raw
1834
2.14M
                }
1835
2.82M
            }
1836
1837
88.4k
            if (c_best) {
1838
26.4k
                free(b->data);
1839
26.4k
                b->data = (unsigned char *)c_best;
1840
26.4k
                b->method = method_best; // adjusted to methmap[method_best] later
1841
26.4k
                b->comp_size = sz_best;
1842
26.4k
            }
1843
1844
            // Accumulate stats for all methods tried
1845
88.4k
            pthread_mutex_lock(&fd->metrics_lock);
1846
2.91M
            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.82M
                metrics->sz[m] += sz[m]+2000;
1852
1853
            // When enough trials performed, find the best on average
1854
88.4k
            if (--metrics->trial == 0) {
1855
19.9k
                int best_method = RAW;
1856
19.9k
                int best_sz = INT_MAX;
1857
1858
                // Relative costs of methods. See enum_cram_block_method_int
1859
                // and methmap
1860
19.9k
                double meth_cost[32] = {
1861
                    // Externally defined methods
1862
19.9k
                    1,    // 0  raw
1863
19.9k
                    1.04, // 1  gzip (Z_FILTERED)
1864
19.9k
                    1.07, // 2  bzip2
1865
19.9k
                    1.08, // 3  lzma
1866
19.9k
                    1.00, // 4  rans    (O0)
1867
19.9k
                    1.00, // 5  ranspr  (O0)
1868
19.9k
                    1.04, // 6  arithpr (O0)
1869
19.9k
                    1.05, // 7  fqz
1870
19.9k
                    1.05, // 8  tok3 (rans)
1871
19.9k
                    1.00, 1.00, // 9,10 reserved
1872
1873
                    // Parameterised versions of above
1874
19.9k
                    1.01, // gzip rle
1875
19.9k
                    1.01, // gzip -1
1876
1877
19.9k
                    1.05, 1.05, 1.05, // FQZ_b,c,d
1878
1879
19.9k
                    1.01, // rans O1
1880
1881
19.9k
                    1.01, // rans_pr1
1882
19.9k
                    1.00, // rans_pr64; if smaller, usually fast
1883
19.9k
                    1.03, // rans_pr65/9
1884
19.9k
                    1.00, // rans_pr128
1885
19.9k
                    1.01, // rans_pr129
1886
19.9k
                    1.00, // rans_pr192
1887
19.9k
                    1.01, // rans_pr193
1888
1889
19.9k
                    1.07, // tok3 arith
1890
1891
19.9k
                    1.04, // arith_pr1
1892
19.9k
                    1.04, // arith_pr64
1893
19.9k
                    1.04, // arith_pr9
1894
19.9k
                    1.03, // arith_pr128
1895
19.9k
                    1.04, // arith_pr129
1896
19.9k
                    1.04, // arith_pr192
1897
19.9k
                    1.04, // arith_pr193
1898
19.9k
                };
1899
1900
                // Scale methods by cost based on compression level
1901
19.9k
                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
19.9k
                } 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
19.9k
                } else if (fd->level <= 6) {
1908
658k
                    for (m = 0; m < CRAM_MAX_METHOD; m++)
1909
638k
                        metrics->sz[m] *= 1+(meth_cost[m]-1)/2;
1910
19.9k
                } 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
19.9k
                metrics->sz[9] = metrics->sz[10] = INT_MAX;
1917
1918
658k
                for (m = 0; m < CRAM_MAX_METHOD; m++) {
1919
638k
                    if ((!metrics->sz[m]) || (!(method & (1u<<m))))
1920
498k
                        continue;
1921
1922
139k
                    if (best_sz > metrics->sz[m])
1923
48.0k
                        best_sz = metrics->sz[m], best_method = m;
1924
139k
                }
1925
1926
19.9k
                if (best_method != metrics->method) {
1927
                    //metrics->trial = (NTRIALS+1)/2; // be sure
1928
                    //metrics->next_trial /= 1.5;
1929
9.47k
                    metrics->consistency = 0;
1930
10.4k
                } else {
1931
10.4k
                    metrics->next_trial *= MIN(2, 1+metrics->consistency/4.0);
1932
10.4k
                    metrics->consistency++;
1933
10.4k
                }
1934
1935
19.9k
                metrics->method = best_method;
1936
19.9k
                switch (best_method) {
1937
151
                case GZIP:     strat = Z_FILTERED; break;
1938
6.69k
                case GZIP_1:   strat = Z_DEFAULT_STRATEGY; break;
1939
6
                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
269
                case TOK3:     strat = 0; break;
1945
0
                case TOKA:     strat = 1; break;
1946
12.8k
                default:       strat = 0;
1947
19.9k
                }
1948
19.9k
                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
203k
#define MAXDELTA 0.20
1955
456k
#define MAXFAILS 4
1956
658k
                for (m = 0; m < CRAM_MAX_METHOD; m++) {
1957
638k
                    if (best_method == m) {
1958
19.9k
                        metrics->cnt[m] = 0;
1959
19.9k
                        metrics->extra[m] = 0;
1960
618k
                    } else if (best_sz < metrics->sz[m]) {
1961
456k
                        double r = (double)metrics->sz[m] / best_sz - 1;
1962
456k
                        int mul = 1+(fd->level>=7);
1963
456k
                        if (++metrics->cnt[m] >= MAXFAILS*mul &&
1964
203k
                            (metrics->extra[m] += r) >= MAXDELTA*mul)
1965
105k
                            method &= ~(1u<<m);
1966
1967
                        // Special case for fqzcomp as it rarely changes
1968
456k
                        if (m == FQZ || m == FQZ_b || m == FQZ_c || m == FQZ_d) {
1969
74.0k
                            if (metrics->sz[m] > best_sz)
1970
74.0k
                                method &= ~(1u<<m);
1971
74.0k
                        }
1972
456k
                    }
1973
638k
                }
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
19.9k
                metrics->revised_method = method;
1979
19.9k
            }
1980
88.4k
            pthread_mutex_unlock(&fd->metrics_lock);
1981
197k
        } else {
1982
197k
            metrics->input_avg_delta =
1983
197k
                0.9 * (metrics->input_avg_delta +
1984
197k
                       ABS(b->uncomp_size - metrics->input_avg_sz));
1985
1986
197k
            metrics->input_avg_sz += b->uncomp_size*.2;
1987
197k
            metrics->input_avg_sz *= 0.8;
1988
1989
197k
            strat = metrics->strat;
1990
197k
            method = metrics->method;
1991
1992
197k
            pthread_mutex_unlock(&fd->metrics_lock);
1993
197k
            comp = cram_compress_by_method(s, (char *)b->data, b->uncomp_size,
1994
197k
                                           b->content_id, &comp_size, method,
1995
197k
                                           method == GZIP_1 ? 1 : level,
1996
197k
                                           strat);
1997
197k
            if (!comp) {
1998
                // Our cached best method failed, but maybe another works?
1999
                // Rerun with trial mode engaged again.
2000
160
                if (!recurse) {
2001
160
                    hts_log_warning("Compressed block ID %d method %s failed, "
2002
160
                                    "redoing trial", b->content_id,
2003
160
                                    cram_block_method2str(method));
2004
160
                    pthread_mutex_lock(&fd->metrics_lock);
2005
160
                    metrics->trial = NTRIALS;
2006
160
                    metrics->next_trial = TRIAL_SPAN;
2007
160
                    metrics->revised_method = orig_method;
2008
160
                    pthread_mutex_unlock(&fd->metrics_lock);
2009
160
                    return cram_compress_block3(fd, s, b, metrics, method,
2010
160
                                                level, 1);
2011
160
                }
2012
0
                return -1;
2013
160
            }
2014
2015
197k
            if (comp_size < b->uncomp_size) {
2016
31.1k
                free(b->data);
2017
31.1k
                b->data = (unsigned char *)comp;
2018
31.1k
                b->comp_size = comp_size;
2019
31.1k
                b->method = method;
2020
166k
            } else {
2021
166k
                free(comp);
2022
166k
            }
2023
197k
        }
2024
2025
285k
    } else {
2026
        // no cached metrics, so just do zlib?
2027
9.57k
        comp = cram_compress_by_method(s, (char *)b->data, b->uncomp_size,
2028
9.57k
                                       b->content_id, &comp_size, GZIP, level, Z_FILTERED);
2029
9.57k
        if (!comp) {
2030
0
            hts_log_error("Compression failed!");
2031
0
            return -1;
2032
0
        }
2033
2034
9.57k
        if (comp_size < b->uncomp_size) {
2035
1.95k
            free(b->data);
2036
1.95k
            b->data = (unsigned char *)comp;
2037
1.95k
            b->comp_size = comp_size;
2038
1.95k
            b->method = GZIP;
2039
7.62k
        } else {
2040
7.62k
            free(comp);
2041
7.62k
        }
2042
9.57k
        strat = Z_FILTERED;
2043
9.57k
    }
2044
2045
295k
    hts_log_info("Compressed block ID %d from %d to %d by method %s",
2046
295k
                 b->content_id, b->uncomp_size, b->comp_size,
2047
295k
                 cram_block_method2str(b->method));
2048
2049
295k
    b->method = methmap[b->method];
2050
2051
295k
    return 0;
2052
295k
}
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
619k
                         int method, int level) {
2063
619k
    return cram_compress_block3(fd, s, b, metrics, method, level, 0);
2064
619k
}
2065
2066
int cram_compress_block(cram_fd *fd, cram_block *b, cram_metrics *metrics,
2067
7.98k
                        int method, int level) {
2068
7.98k
    return cram_compress_block2(fd, NULL, b, metrics, method, level);
2069
7.98k
}
2070
2071
783k
cram_metrics *cram_new_metrics(void) {
2072
783k
    cram_metrics *m = calloc(1, sizeof(*m));
2073
783k
    if (!m)
2074
0
        return NULL;
2075
783k
    m->trial = NTRIALS-1;
2076
783k
    m->next_trial = TRIAL_SPAN/2; // learn quicker at start
2077
783k
    m->method = RAW;
2078
783k
    m->strat = 0;
2079
783k
    m->revised_method = 0;
2080
783k
    m->unpackable = 0;
2081
2082
783k
    return m;
2083
783k
}
2084
2085
295k
char *cram_block_method2str(enum cram_block_method_int m) {
2086
295k
    switch(m) {
2087
235k
    case RAW:         return "RAW";
2088
5.86k
    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
85
    case GZIP_RLE:    return "GZIP_RLE";
2094
6.94k
    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
907
    case RANS_PR0:    return "RANS_PR0";
2100
413
    case RANS_PR1:    return "RANS_PR1";
2101
21.3k
    case RANS_PR64:   return "RANS_PR64";
2102
17
    case RANS_PR9:    return "RANS_PR9";
2103
23.8k
    case RANS_PR128:  return "RANS_PR128";
2104
0
    case RANS_PR129:  return "RANS_PR129";
2105
0
    case RANS_PR192:  return "RANS_PR192";
2106
209
    case RANS_PR193:  return "RANS_PR193";
2107
179
    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
295k
    }
2119
0
    return "?";
2120
295k
}
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
4.53k
static void ref_entry_free_seq(ref_entry *e) {
2162
4.53k
    if (e->mf)
2163
0
        mfclose(e->mf);
2164
4.53k
    if (e->seq && !e->mf)
2165
0
        free(e->seq);
2166
2167
4.53k
    e->seq = NULL;
2168
4.53k
    e->mf = NULL;
2169
4.53k
}
2170
2171
16.5k
void refs_free(refs_t *r) {
2172
16.5k
    RP("refs_free()\n");
2173
2174
16.5k
    if (!r)
2175
0
        return;
2176
2177
16.5k
    if (--r->count > 0)
2178
0
        return;
2179
2180
16.5k
    if (r->pool)
2181
16.5k
        string_pool_destroy(r->pool);
2182
2183
16.5k
    if (r->h_meta) {
2184
16.5k
        khint_t k;
2185
2186
30.3k
        for (k = kh_begin(r->h_meta); k != kh_end(r->h_meta); k++) {
2187
13.8k
            ref_entry *e;
2188
2189
13.8k
            if (!kh_exist(r->h_meta, k))
2190
9.31k
                continue;
2191
4.53k
            if (!(e = kh_val(r->h_meta, k)))
2192
0
                continue;
2193
4.53k
            ref_entry_free_seq(e);
2194
4.53k
            free(e);
2195
4.53k
        }
2196
2197
16.5k
        kh_destroy(refs, r->h_meta);
2198
16.5k
    }
2199
2200
16.5k
    if (r->ref_id)
2201
8.16k
        free(r->ref_id);
2202
2203
16.5k
    if (r->fp)
2204
0
        bgzf_close(r->fp);
2205
2206
16.5k
    pthread_mutex_destroy(&r->lock);
2207
2208
16.5k
    free(r);
2209
16.5k
}
2210
2211
16.5k
static refs_t *refs_create(void) {
2212
16.5k
    refs_t *r = calloc(1, sizeof(*r));
2213
2214
16.5k
    RP("refs_create()\n");
2215
2216
16.5k
    if (!r)
2217
0
        return NULL;
2218
2219
16.5k
    if (!(r->pool = string_pool_create(8192)))
2220
0
        goto err;
2221
2222
16.5k
    r->ref_id = NULL; // see refs2id() to populate.
2223
16.5k
    r->count = 1;
2224
16.5k
    r->last = NULL;
2225
16.5k
    r->last_id = -1;
2226
2227
16.5k
    if (!(r->h_meta = kh_init(refs)))
2228
0
        goto err;
2229
2230
16.5k
    pthread_mutex_init(&r->lock, NULL);
2231
2232
16.5k
    return r;
2233
2234
0
 err:
2235
0
    refs_free(r);
2236
0
    return NULL;
2237
16.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.26k
static BGZF *bgzf_open_ref(char *fn, char *mode, int is_md5) {
2248
1.26k
    BGZF *fp;
2249
2250
1.26k
    if (strncmp(fn, "file://", 7) == 0)
2251
12
        fn += 7;
2252
2253
1.26k
    if (!is_md5 && !hisremote(fn)) {
2254
882
        char fai_file[PATH_MAX];
2255
2256
882
        snprintf(fai_file, PATH_MAX, "%s.fai", fn);
2257
882
        if (access(fai_file, R_OK) != 0)
2258
882
            if (fai_build(fn) != 0)
2259
882
                return NULL;
2260
882
    }
2261
2262
380
    if (!(fp = bgzf_open(fn, mode))) {
2263
380
        perror(fn);
2264
380
        return NULL;
2265
380
    }
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.26k
static refs_t *refs_load_fai(refs_t *r_orig, const char *fn, int is_err) {
2286
1.26k
    hFILE *fp = NULL;
2287
1.26k
    char fai_fn[PATH_MAX];
2288
1.26k
    char line[8192];
2289
1.26k
    refs_t *r = r_orig;
2290
1.26k
    size_t fn_l = strlen(fn);
2291
1.26k
    int id = 0, id_alloc = 0;
2292
2293
1.26k
    RP("refs_load_fai %s\n", fn);
2294
2295
1.26k
    if (!r)
2296
0
        if (!(r = refs_create()))
2297
0
            goto err;
2298
2299
1.26k
    if (r->fp)
2300
0
        if (bgzf_close(r->fp) != 0)
2301
0
            goto err;
2302
1.26k
    r->fp = NULL;
2303
2304
    /* Look for a FASTA##idx##FAI format */
2305
1.26k
    const char *fn_delim = strstr(fn, HTS_IDX_DELIM);
2306
1.26k
    if (fn_delim) {
2307
21
        if (!(r->fn = string_ndup(r->pool, fn, fn_delim - fn)))
2308
0
            goto err;
2309
21
        fn_delim += strlen(HTS_IDX_DELIM);
2310
21
        snprintf(fai_fn, PATH_MAX, "%s", fn_delim);
2311
1.24k
    } else {
2312
        /* An index file was provided, instead of the actual reference file */
2313
1.24k
        if (fn_l > 4 && strcmp(&fn[fn_l-4], ".fai") == 0) {
2314
4
            if (!r->fn) {
2315
3
                if (!(r->fn = string_ndup(r->pool, fn, fn_l-4)))
2316
0
                    goto err;
2317
3
            }
2318
4
            snprintf(fai_fn, PATH_MAX, "%s", fn);
2319
1.23k
        } else {
2320
        /* Only the reference file provided. Get the index file name from it */
2321
1.23k
            if (!(r->fn = string_dup(r->pool, fn)))
2322
0
                goto err;
2323
1.23k
            snprintf(fai_fn, PATH_MAX, "%.*s.fai", PATH_MAX-5, fn);
2324
1.23k
        }
2325
1.24k
    }
2326
2327
1.26k
    if (!(r->fp = bgzf_open_ref(r->fn, "r", 0))) {
2328
1.26k
        hts_log_error("Failed to open reference file '%s'", r->fn);
2329
1.26k
        goto err;
2330
1.26k
    }
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.26k
 err:
2425
1.26k
    if (fp)
2426
0
        hclose_abruptly(fp);
2427
2428
1.26k
    if (!r_orig)
2429
0
        refs_free(r);
2430
2431
1.26k
    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
7.98k
int refs2id(refs_t *r, sam_hdr_t *hdr) {
2482
7.98k
    int i;
2483
7.98k
    sam_hrecs_t *h = hdr->hrecs;
2484
2485
7.98k
    if (r->ref_id)
2486
2.69k
        free(r->ref_id);
2487
7.98k
    if (r->last)
2488
0
        r->last = NULL;
2489
2490
7.98k
    r->ref_id = calloc(h->nref, sizeof(*r->ref_id));
2491
7.98k
    if (!r->ref_id)
2492
0
        return -1;
2493
2494
7.98k
    r->nref = h->nref;
2495
11.5k
    for (i = 0; i < h->nref; i++) {
2496
3.58k
        khint_t k = kh_get(refs, r->h_meta, h->ref[i].name);
2497
3.58k
        if (k != kh_end(r->h_meta)) {
2498
3.58k
            r->ref_id[i] = kh_val(r->h_meta, k);
2499
3.58k
        } else {
2500
0
            hts_log_warning("Unable to find ref name '%s'", h->ref[i].name);
2501
0
        }
2502
3.58k
    }
2503
2504
7.98k
    return 0;
2505
7.98k
}
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
32.5k
static int refs_from_header(cram_fd *fd) {
2513
32.5k
    if (!fd)
2514
0
        return -1;
2515
2516
32.5k
    refs_t *r = fd->refs;
2517
32.5k
    if (!r)
2518
0
        return -1;
2519
2520
32.5k
    sam_hdr_t *h = fd->header;
2521
32.5k
    if (!h)
2522
8.58k
        return 0;
2523
2524
23.9k
    if (!h->hrecs) {
2525
15.4k
        if (-1 == sam_hdr_fill_hrecs(h))
2526
112
            return -1;
2527
15.4k
    }
2528
2529
23.8k
    if (h->hrecs->nref == 0)
2530
18.3k
        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
5.57k
    ref_entry **new_ref_id = hts_realloc_ps(r->ref_id, sizeof(*r->ref_id),
2536
5.57k
                                            r->nref, h->hrecs->nref);
2537
5.57k
    if (!new_ref_id)
2538
0
        return -1;
2539
5.57k
    r->ref_id = new_ref_id;
2540
2541
5.57k
    int i, j;
2542
    /* Copy info from h->ref[i] over to r */
2543
13.7k
    for (i = 0, j = r->nref; i < h->hrecs->nref; i++) {
2544
8.12k
        sam_hrec_type_t *ty;
2545
8.12k
        sam_hrec_tag_t *tag;
2546
8.12k
        khint_t k;
2547
8.12k
        int n;
2548
2549
8.12k
        k = kh_get(refs, r->h_meta, h->hrecs->ref[i].name);
2550
8.12k
        if (k != kh_end(r->h_meta))
2551
            // Ref already known about
2552
3.58k
            continue;
2553
2554
4.53k
        if (!(r->ref_id[j] = calloc(1, sizeof(ref_entry))))
2555
0
            return -1;
2556
2557
4.53k
        if (!h->hrecs->ref[i].name)
2558
0
            return -1;
2559
2560
4.53k
        r->ref_id[j]->name = string_dup(r->pool, h->hrecs->ref[i].name);
2561
4.53k
        if (!r->ref_id[j]->name) return -1;
2562
4.53k
        r->ref_id[j]->length = 0; // marker for not yet loaded
2563
2564
        /* Initialise likely filename if known */
2565
4.53k
        if ((ty = sam_hrecs_find_type_id(h->hrecs, "SQ", "SN", h->hrecs->ref[i].name))) {
2566
4.53k
            if ((tag = sam_hrecs_find_key(ty, "M5", NULL)))
2567
139
                r->ref_id[j]->fn = string_dup(r->pool, tag->str+3);
2568
2569
4.53k
            if ((tag = sam_hrecs_find_key(ty, "LN", NULL))) {
2570
                // LN tag used when constructing consensus reference
2571
4.53k
                r->ref_id[j]->LN_length = strtoll(tag->str+3, NULL, 0);
2572
                // See fuzz 382922241
2573
4.53k
                if (r->ref_id[j]->LN_length < 0)
2574
0
                    r->ref_id[j]->LN_length = 0;
2575
4.53k
            }
2576
4.53k
        }
2577
2578
4.53k
        k = kh_put(refs, r->h_meta, r->ref_id[j]->name, &n);
2579
4.53k
        if (n <= 0) // already exists or error
2580
0
            return -1;
2581
4.53k
        kh_val(r->h_meta, k) = r->ref_id[j];
2582
2583
4.53k
        j++;
2584
4.53k
    }
2585
5.57k
    r->nref = j;
2586
2587
5.57k
    return 0;
2588
5.57k
}
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
8.09k
int cram_set_header2(cram_fd *fd, const sam_hdr_t *hdr) {
2598
8.09k
    if (!fd || !hdr )
2599
0
        return -1;
2600
2601
8.09k
    if (fd->header != hdr) {
2602
8.09k
        if (fd->header)
2603
0
            sam_hdr_destroy(fd->header);
2604
8.09k
        fd->header = sam_hdr_dup(hdr);
2605
8.09k
        if (!fd->header)
2606
0
            return -1;
2607
8.09k
    }
2608
8.09k
    return refs_from_header(fd);
2609
8.09k
}
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
2.98k
static int cram_populate_ref(cram_fd *fd, int id, ref_entry *r) {
2723
2.98k
    char *ref_path = getenv("REF_PATH");
2724
2.98k
    sam_hrec_type_t *ty;
2725
2.98k
    sam_hrec_tag_t *tag;
2726
2.98k
    char path[PATH_MAX];
2727
2.98k
    kstring_t path_tmp = KS_INITIALIZE;
2728
2.98k
    char *local_cache = getenv("REF_CACHE");
2729
2.98k
    mFILE *mf;
2730
2.98k
    int local_path = 0;
2731
2732
2.98k
    hts_log_info("Running cram_populate_ref on fd %p, id %d", (void *)fd, id);
2733
2734
2.98k
    if (!r->name)
2735
0
        return -1;
2736
2737
2.98k
    if (!(ty = sam_hrecs_find_type_id(fd->header->hrecs, "SQ", "SN", r->name)))
2738
0
        return -1;
2739
2740
2.98k
    if (!(tag = sam_hrecs_find_key(ty, "M5", NULL)))
2741
2.95k
        goto no_M5;
2742
2743
25
    hts_log_info("Querying ref %s", tag->str+3);
2744
2745
    /* Use cache if available */
2746
25
    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
25
    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
25
    int is_local = 0;
2795
25
    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
25
    } else {
2809
25
        refs_t *refs;
2810
25
        const char *fn;
2811
25
        sam_hrec_tag_t *UR_tag;
2812
2813
2.98k
    no_M5:
2814
        /* Failed to find in search path or M5 cache, see if @SQ UR: tag? */
2815
2.98k
        if (!(UR_tag = sam_hrecs_find_key(ty, "UR", NULL)))
2816
1.69k
            return -1;
2817
2818
1.28k
        if (strstr(UR_tag->str+3, "://") &&
2819
157
            strncmp(UR_tag->str+3, "file:", 5) != 0) {
2820
            // Documented as omitted, but accidentally supported until now
2821
25
            hts_log_error("UR tags pointing to remote files are not supported");
2822
25
            return -1;
2823
25
        }
2824
2825
1.26k
        fn = (strncmp(UR_tag->str+3, "file:", 5) == 0)
2826
1.26k
            ? UR_tag->str+8
2827
1.26k
            : UR_tag->str+3;
2828
2829
1.26k
        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.26k
        if (!(refs = refs_load_fai(fd->refs, fn, 0)))
2835
1.26k
            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
2.09k
static void cram_ref_incr_locked(refs_t *r, int id) {
2915
2.09k
    RP("%d INC REF %d, %d %p\n", gettid(), id,
2916
2.09k
       (int)(id>=0 && r->ref_id[id]?r->ref_id[id]->count+1:-999),
2917
2.09k
       id>=0 && r->ref_id[id]?r->ref_id[id]->seq:(char *)1);
2918
2919
2.09k
    if (id < 0 || !r->ref_id[id] || !r->ref_id[id]->seq)
2920
2.09k
        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
2.09k
void cram_ref_incr(refs_t *r, int id) {
2929
2.09k
    pthread_mutex_lock(&r->lock);
2930
2.09k
    cram_ref_incr_locked(r, id);
2931
2.09k
    pthread_mutex_unlock(&r->lock);
2932
2.09k
}
2933
2934
145
static void cram_ref_decr_locked(refs_t *r, int id) {
2935
145
    RP("%d DEC REF %d, %d %p\n", gettid(), id,
2936
145
       (int)(id>=0 && r->ref_id[id]?r->ref_id[id]->count-1:-999),
2937
145
       id>=0 && r->ref_id[id]?r->ref_id[id]->seq:(char *)1);
2938
2939
145
    if (id < 0 || !r->ref_id[id] || !r->ref_id[id]->seq) {
2940
145
        return;
2941
145
    }
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
145
void cram_ref_decr(refs_t *r, int id) {
2959
145
    pthread_mutex_lock(&r->lock);
2960
145
    cram_ref_decr_locked(r, id);
2961
145
    pthread_mutex_unlock(&r->lock);
2962
145
}
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
6.10k
char *cram_get_ref(cram_fd *fd, int id, hts_pos_t start, hts_pos_t end) {
3155
6.10k
    ref_entry *r;
3156
6.10k
    char *seq;
3157
6.10k
    int ostart = start;
3158
3159
6.10k
    if (id == -1 || start < 1)
3160
3.11k
        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
2.99k
    pthread_mutex_lock(&fd->ref_lock);
3169
3170
2.99k
    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
2.99k
    if (fd->unsorted)
3178
0
        fd->shared_ref = 1;
3179
3180
3181
    /* Sanity checking: does this ID exist? */
3182
2.99k
    if (!fd->refs || id < 0 || id >= fd->refs->nref || !fd->refs->ref_id[id]) {
3183
15
        hts_log_error("No reference found for id %d", id);
3184
15
        pthread_mutex_unlock(&fd->ref_lock);
3185
15
        return NULL;
3186
15
    }
3187
3188
2.98k
    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
2.98k
    pthread_mutex_lock(&fd->refs->lock);
3202
2.98k
    if (r->length == 0) {
3203
2.98k
        if (fd->ref_fn)
3204
0
            hts_log_warning("Reference file given, but ref '%s' not present",
3205
2.98k
                            r->name);
3206
2.98k
        if (cram_populate_ref(fd, id, r) == -1) {
3207
2.98k
            hts_log_warning("Failed to populate reference \"%s\"",
3208
2.98k
                            r->name);
3209
2.98k
            hts_log_warning("See https://www.htslib.org/doc/reference_seqs.html for further suggestions");
3210
2.98k
            pthread_mutex_unlock(&fd->refs->lock);
3211
2.98k
            pthread_mutex_unlock(&fd->ref_lock);
3212
2.98k
            return NULL;
3213
2.98k
        }
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
48.4k
cram_container *cram_new_container(int nrec, int nslice) {
3383
48.4k
    cram_container *c = calloc(1, sizeof(*c));
3384
48.4k
    enum cram_DS_ID id;
3385
3386
48.4k
    if (!c)
3387
0
        return NULL;
3388
3389
48.4k
    c->curr_ref = -2;
3390
3391
48.4k
    c->max_c_rec = nrec * nslice;
3392
48.4k
    c->curr_c_rec = 0;
3393
3394
48.4k
    c->max_rec = nrec;
3395
48.4k
    c->record_counter = 0;
3396
48.4k
    c->num_bases = 0;
3397
48.4k
    c->s_num_bases = 0;
3398
3399
48.4k
    c->max_slice = nslice;
3400
48.4k
    c->curr_slice = 0;
3401
3402
48.4k
    c->pos_sorted = 1;
3403
48.4k
    c->max_apos   = 0;
3404
48.4k
    c->multi_seq  = 0;
3405
48.4k
    c->qs_seq_orient = 1;
3406
48.4k
    c->no_ref = 0;
3407
48.4k
    c->embed_ref = -1; // automatic selection
3408
3409
48.4k
    c->bams = NULL;
3410
3411
48.4k
    if (!(c->slices = calloc(nslice != 0 ? nslice : 1, sizeof(cram_slice *))))
3412
0
        goto err;
3413
48.4k
    c->slice = NULL;
3414
3415
48.4k
    if (!(c->comp_hdr = cram_new_compression_header()))
3416
0
        goto err;
3417
48.4k
    c->comp_hdr_block = NULL;
3418
3419
1.40M
    for (id = DS_RN; id < DS_TN; id++)
3420
1.35M
        if (!(c->stats[id] = cram_stats_create())) goto err;
3421
3422
    //c->aux_B_stats = cram_stats_create();
3423
3424
48.4k
    if (!(c->tags_used = kh_init(m_tagmap)))
3425
0
        goto err;
3426
48.4k
    c->refs_used = 0;
3427
48.4k
    c->ref_free = 0;
3428
3429
48.4k
    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
48.4k
}
3439
3440
4.22k
static void free_bam_list(bam_seq_t *bams, int max_rec) {
3441
4.22k
    int i;
3442
42.2M
    for (i = 0; i < max_rec; i++)
3443
42.2M
        bam_free(&bams[i]);
3444
3445
4.22k
    free(bams);
3446
4.22k
}
3447
3448
71.3k
void cram_free_container(cram_container *c) {
3449
71.3k
    enum cram_DS_ID id;
3450
71.3k
    int i;
3451
3452
71.3k
    if (!c)
3453
0
        return;
3454
3455
71.3k
    if (c->refs_used)
3456
1.01k
        free(c->refs_used);
3457
3458
71.3k
    if (c->landmark)
3459
49.9k
        free(c->landmark);
3460
3461
71.3k
    if (c->comp_hdr)
3462
49.5k
        cram_free_compression_header(c->comp_hdr);
3463
3464
71.3k
    if (c->comp_hdr_block)
3465
45.5k
        cram_free_block(c->comp_hdr_block);
3466
3467
    // Free the slices; filled out by encoder only
3468
71.3k
    if (c->slices) {
3469
88.9k
        for (i = 0; i < c->max_slice; i++) {
3470
40.4k
            if (c->slices[i])
3471
4.22k
                cram_free_slice(c->slices[i]);
3472
40.4k
            if (c->slices[i] == c->slice)
3473
40.4k
                c->slice = NULL;
3474
40.4k
        }
3475
48.4k
        free(c->slices);
3476
48.4k
    }
3477
3478
    // Free the current slice; set by both encoder & decoder
3479
71.3k
    if (c->slice) {
3480
0
        cram_free_slice(c->slice);
3481
0
        c->slice = NULL;
3482
0
    }
3483
3484
2.06M
    for (id = DS_RN; id < DS_TN; id++)
3485
1.99M
        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
71.3k
    if (c->tags_used) {
3490
48.4k
        khint_t k;
3491
3492
243k
        for (k = kh_begin(c->tags_used); k != kh_end(c->tags_used); k++) {
3493
195k
            if (!kh_exist(c->tags_used, k))
3494
105k
                continue;
3495
3496
89.3k
            cram_tag_map *tm = (cram_tag_map *)kh_val(c->tags_used, k);
3497
89.3k
            if (tm) {
3498
89.3k
                cram_codec *c = tm->codec;
3499
3500
89.3k
                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
89.3k
                cram_free_block(tm->blk);
3508
89.3k
                cram_free_block(tm->blk2);
3509
89.3k
                free(tm);
3510
89.3k
            }
3511
89.3k
        }
3512
3513
48.4k
        kh_destroy(m_tagmap, c->tags_used);
3514
48.4k
    }
3515
3516
71.3k
    if (c->ref_free)
3517
18.9k
        free(c->ref);
3518
3519
71.3k
    if (c->bams)
3520
624
        free_bam_list(c->bams, c->max_c_rec);
3521
3522
71.3k
    free(c);
3523
71.3k
}
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
23.2k
cram_container *cram_read_container(cram_fd *fd) {
3532
23.2k
    cram_container c2, *c;
3533
23.2k
    int i, s;
3534
23.2k
    size_t rd = 0;
3535
23.2k
    uint32_t crc = 0;
3536
3537
23.2k
    fd->err = 0;
3538
23.2k
    fd->eof = 0;
3539
3540
23.2k
    memset(&c2, 0, sizeof(c2));
3541
23.2k
    if (CRAM_MAJOR_VERS(fd->version) == 1) {
3542
9.33k
        if ((s = fd->vv.varint_decode32_crc(fd, &c2.length, &crc)) == -1) {
3543
66
            fd->eof = fd->empty_container ? 1 : 2;
3544
66
            return NULL;
3545
9.27k
        } else {
3546
9.27k
            rd+=s;
3547
9.27k
        }
3548
13.8k
    } else if (CRAM_MAJOR_VERS(fd->version) < 4) {
3549
6.37k
        uint32_t len;
3550
6.37k
        if ((s = int32_decode(fd, &c2.length)) == -1) {
3551
19
            if (CRAM_MAJOR_VERS(fd->version) == 2 &&
3552
12
                CRAM_MINOR_VERS(fd->version) == 0)
3553
5
                fd->eof = 1; // EOF blocks arrived in v2.1
3554
14
            else
3555
14
                fd->eof = fd->empty_container ? 1 : 2;
3556
19
            return NULL;
3557
6.35k
        } else {
3558
6.35k
            rd+=s;
3559
6.35k
        }
3560
6.35k
        len = le_int4(c2.length);
3561
6.35k
        crc = crc32(0L, (unsigned char *)&len, 4);
3562
6.35k
    }
3563
23.1k
    if ((s = fd->vv.varint_decode32s_crc(fd, &c2.ref_seq_id, &crc))   == -1) return NULL; else rd+=s;
3564
23.1k
    int32_t i32;
3565
23.1k
    if ((s = fd->vv.varint_decode32_crc(fd, &i32, &crc))== -1) return NULL; else rd+=s;
3566
23.0k
    c2.ref_seq_start = i32;
3567
23.0k
    if ((s = fd->vv.varint_decode32_crc(fd, &i32, &crc)) == -1) return NULL; else rd+=s;
3568
23.0k
    c2.ref_seq_span = i32;
3569
23.0k
    if ((s = fd->vv.varint_decode32_crc(fd, &c2.num_records, &crc))  == -1) return NULL; else rd+=s;
3570
3571
23.0k
    if (CRAM_MAJOR_VERS(fd->version) == 1) {
3572
9.18k
        c2.record_counter = 0;
3573
9.18k
        c2.num_bases = 0;
3574
13.8k
    } else {
3575
13.8k
        if (CRAM_MAJOR_VERS(fd->version) >= 3) {
3576
7.87k
            if ((s = fd->vv.varint_decode64_crc(fd, &c2.record_counter, &crc)) == -1)
3577
22
                return NULL;
3578
7.85k
            else
3579
7.85k
                rd += s;
3580
7.87k
        } else {
3581
5.96k
            int32_t i32;
3582
5.96k
            if ((s = fd->vv.varint_decode32_crc(fd, &i32, &crc)) == -1)
3583
10
                return NULL;
3584
5.95k
            else
3585
5.95k
                rd += s;
3586
5.95k
            c2.record_counter = i32;
3587
5.95k
        }
3588
3589
13.8k
        if ((s = fd->vv.varint_decode64_crc(fd, &c2.num_bases, &crc))== -1)
3590
39
            return NULL;
3591
13.7k
        else
3592
13.7k
            rd += s;
3593
13.8k
    }
3594
22.9k
    if ((s = fd->vv.varint_decode32_crc(fd, &c2.num_blocks, &crc))   == -1)
3595
20
        return NULL;
3596
22.9k
    else
3597
22.9k
        rd+=s;
3598
22.9k
    if ((s = fd->vv.varint_decode32_crc(fd, &c2.num_landmarks, &crc))== -1)
3599
13
        return NULL;
3600
22.9k
    else
3601
22.9k
        rd+=s;
3602
3603
22.9k
    if (c2.num_landmarks < 0 || c2.num_landmarks >= SIZE_MAX / sizeof(int32_t))
3604
49
        return NULL;
3605
3606
22.8k
    if (!(c = calloc(1, sizeof(*c))))
3607
0
        return NULL;
3608
3609
22.8k
    *c = c2;
3610
22.8k
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
3611
22.8k
    if (c->num_landmarks > FUZZ_ALLOC_LIMIT/sizeof(int32_t)) {
3612
4
        fd->err = errno = ENOMEM;
3613
4
        cram_free_container(c);
3614
4
        return NULL;
3615
4
    }
3616
22.8k
#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
22.8k
    if (c->num_landmarks > 1000000) {
3623
26
        cram_free_container(c);
3624
26
        return NULL;
3625
26
    }
3626
22.8k
    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
115k
    for (i = 0; i < c->num_landmarks; i++) {
3632
93.1k
        if ((s = fd->vv.varint_decode32_crc(fd, &c->landmark[i], &crc)) == -1) {
3633
157
            cram_free_container(c);
3634
157
            return NULL;
3635
93.0k
        } else {
3636
93.0k
            rd += s;
3637
93.0k
        }
3638
93.1k
    }
3639
3640
22.6k
    if (CRAM_MAJOR_VERS(fd->version) >= 3) {
3641
7.74k
        if (-1 == int32_decode(fd, (int32_t *)&c->crc32)) {
3642
17
            cram_free_container(c);
3643
17
            return NULL;
3644
7.73k
        } else {
3645
7.73k
            rd+=4;
3646
7.73k
        }
3647
3648
7.73k
#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.73k
        crc = c->crc32;
3651
7.73k
#endif
3652
3653
7.73k
        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.73k
    }
3659
3660
22.6k
    c->offset = rd;
3661
22.6k
    c->slices = NULL;
3662
22.6k
    c->slice = NULL;
3663
22.6k
    c->curr_slice = 0;
3664
22.6k
    c->max_slice = c->num_landmarks;
3665
22.6k
    c->slice_rec = 0;
3666
22.6k
    c->curr_rec = 0;
3667
22.6k
    c->max_rec = 0;
3668
3669
22.6k
    if (c->ref_seq_id == -2) {
3670
67
        c->multi_seq = 1;
3671
67
        fd->multi_seq = 1;
3672
67
    }
3673
3674
22.6k
    fd->empty_container =
3675
22.6k
        (c->num_records == 0 &&
3676
14.3k
         c->ref_seq_id == -1 &&
3677
22.6k
         c->ref_seq_start == 0x454f46 /* EOF */) ? 1 : 0;
3678
3679
22.6k
    return c;
3680
22.6k
}
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
55.2k
int cram_write_container(cram_fd *fd, cram_container *c) {
3756
55.2k
    char buf_a[1024], *buf = buf_a, *cp;
3757
55.2k
    int i;
3758
3759
55.2k
    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
55.2k
    cp = buf;
3765
3766
55.2k
    if (CRAM_MAJOR_VERS(fd->version) == 1) {
3767
0
        cp += itf8_put(cp, c->length);
3768
55.2k
    } else if (CRAM_MAJOR_VERS(fd->version) <= 3) {
3769
55.2k
        *(int32_t *)cp = le_int4(c->length);
3770
55.2k
        cp += 4;
3771
55.2k
    } else {
3772
0
        cp += fd->vv.varint_put32(cp, NULL, c->length);
3773
0
    }
3774
55.2k
    if (c->multi_seq) {
3775
1.01k
        cp += fd->vv.varint_put32(cp, NULL, (uint32_t)-2);
3776
1.01k
        cp += fd->vv.varint_put32(cp, NULL, 0);
3777
1.01k
        cp += fd->vv.varint_put32(cp, NULL, 0);
3778
54.2k
    } else {
3779
54.2k
        cp += fd->vv.varint_put32s(cp, NULL, c->ref_seq_id);
3780
54.2k
        cp += fd->vv.varint_put32(cp, NULL, c->ref_seq_start);
3781
54.2k
        cp += fd->vv.varint_put32(cp, NULL, c->ref_seq_span);
3782
54.2k
    }
3783
55.2k
    cp += fd->vv.varint_put32(cp, NULL, c->num_records);
3784
55.2k
    if (CRAM_MAJOR_VERS(fd->version) >= 3)
3785
55.2k
        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
55.2k
    cp += fd->vv.varint_put64(cp, NULL, c->num_bases);
3789
55.2k
    cp += fd->vv.varint_put32(cp, NULL, c->num_blocks);
3790
55.2k
    cp += fd->vv.varint_put32(cp, NULL, c->num_landmarks);
3791
110k
    for (i = 0; i < c->num_landmarks; i++)
3792
55.5k
        cp += fd->vv.varint_put32(cp, NULL, c->landmark[i]);
3793
3794
55.2k
    if (CRAM_MAJOR_VERS(fd->version) >= 3) {
3795
55.2k
        c->crc32 = crc32(0L, (uc *)buf, cp-buf);
3796
55.2k
        cp[0] =  c->crc32        & 0xff;
3797
55.2k
        cp[1] = (c->crc32 >>  8) & 0xff;
3798
55.2k
        cp[2] = (c->crc32 >> 16) & 0xff;
3799
55.2k
        cp[3] = (c->crc32 >> 24) & 0xff;
3800
55.2k
        cp += 4;
3801
55.2k
    }
3802
3803
55.2k
    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
55.2k
    if (buf != buf_a)
3810
0
        free(buf);
3811
3812
55.2k
    return 0;
3813
55.2k
}
3814
3815
// common component shared by cram_flush_container{,_mt}
3816
39.5k
static int cram_flush_container2(cram_fd *fd, cram_container *c) {
3817
39.5k
    int i, j;
3818
3819
39.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
39.5k
    off_t c_offset = htell(fd->fp); // File offset of container
3825
3826
    /* Write the container struct itself */
3827
39.5k
    if (0 != cram_write_container(fd, c))
3828
0
        return -1;
3829
3830
39.5k
    off_t hdr_size = htell(fd->fp) - c_offset;
3831
3832
    /* And the compression header */
3833
39.5k
    if (0 != cram_write_block(fd, c->comp_hdr_block))
3834
0
        return -1;
3835
3836
    /* Followed by the slice blocks */
3837
39.5k
    off_t file_offset = htell(fd->fp);
3838
79.1k
    for (i = 0; i < c->curr_slice; i++) {
3839
39.5k
        cram_slice *s = c->slices[i];
3840
39.5k
        off_t spos = file_offset - c_offset - hdr_size;
3841
3842
39.5k
        if (0 != cram_write_block(fd, s->hdr_block))
3843
0
            return -1;
3844
3845
313k
        for (j = 0; j < s->hdr->num_blocks; j++) {
3846
273k
            if (0 != cram_write_block(fd, s->block[j]))
3847
0
                return -1;
3848
273k
        }
3849
3850
39.5k
        file_offset = htell(fd->fp);
3851
39.5k
        off_t sz = file_offset - c_offset - hdr_size - spos;
3852
3853
39.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
39.5k
    }
3858
3859
39.5k
    return 0;
3860
39.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
40.4k
int cram_flush_container(cram_fd *fd, cram_container *c) {
3871
    /* Encode the container blocks and generate compression header */
3872
40.4k
    if (0 != cram_encode_container(fd, c))
3873
930
        return -1;
3874
3875
39.5k
    return cram_flush_container2(fd, c);
3876
40.4k
}
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.29k
void reset_metrics(cram_fd *fd) {
3966
3.29k
    int i;
3967
3968
3.29k
    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
158k
    for (i = 0; i < DS_END; i++) {
3989
154k
        cram_metrics *m = fd->m[i];
3990
154k
        if (!m)
3991
0
            continue;
3992
3993
154k
        m->trial = NTRIALS;
3994
154k
        m->next_trial = TRIAL_SPAN;
3995
154k
        m->revised_method = 0;
3996
154k
        m->unpackable = 0;
3997
3998
154k
        memset(m->sz, 0, sizeof(m->sz));
3999
154k
    }
4000
3.29k
}
4001
4002
40.4k
int cram_flush_container_mt(cram_fd *fd, cram_container *c) {
4003
40.4k
    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
40.4k
    pthread_mutex_lock(&fd->metrics_lock);
4016
40.4k
    if (c->n_mapped < 0.3*c->curr_rec &&
4017
21.5k
        fd->last_mapped > 0.7*c->max_rec) {
4018
3.29k
        reset_metrics(fd);
4019
3.29k
    }
4020
40.4k
    fd->last_mapped = c->n_mapped * (c->max_rec+1)/(c->curr_rec+1) ;
4021
40.4k
    pthread_mutex_unlock(&fd->metrics_lock);
4022
4023
40.4k
    if (!fd->pool)
4024
40.4k
        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
48.4k
cram_block_compression_hdr *cram_new_compression_header(void) {
4060
48.4k
    cram_block_compression_hdr *hdr = calloc(1, sizeof(*hdr));
4061
48.4k
    if (!hdr)
4062
0
        return NULL;
4063
4064
48.4k
    if (!(hdr->TD_blk = cram_new_block(CORE, 0))) {
4065
0
        free(hdr);
4066
0
        return NULL;
4067
0
    }
4068
4069
48.4k
    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
48.4k
    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
48.4k
    return hdr;
4083
48.4k
}
4084
4085
50.9k
void cram_free_compression_header(cram_block_compression_hdr *hdr) {
4086
50.9k
    int i;
4087
4088
50.9k
    if (hdr->landmark)
4089
2.45k
        free(hdr->landmark);
4090
4091
50.9k
    if (hdr->preservation_map)
4092
42.0k
        kh_destroy(map, hdr->preservation_map);
4093
4094
1.68M
    for (i = 0; i < CRAM_MAP_HASH; i++) {
4095
1.62M
        cram_map *m, *m2;
4096
1.65M
        for (m = hdr->rec_encoding_map[i]; m; m = m2) {
4097
22.2k
            m2 = m->next;
4098
22.2k
            if (m->codec)
4099
0
                m->codec->free(m->codec);
4100
22.2k
            free(m);
4101
22.2k
        }
4102
1.62M
    }
4103
4104
1.68M
    for (i = 0; i < CRAM_MAP_HASH; i++) {
4105
1.62M
        cram_map *m, *m2;
4106
1.63M
        for (m = hdr->tag_encoding_map[i]; m; m = m2) {
4107
603
            m2 = m->next;
4108
603
            if (m->codec)
4109
603
                m->codec->free(m->codec);
4110
603
            free(m);
4111
603
        }
4112
1.62M
    }
4113
4114
2.44M
    for (i = 0; i < DS_END; i++) {
4115
2.39M
        if (hdr->codecs[i])
4116
755k
            hdr->codecs[i]->free(hdr->codecs[i]);
4117
2.39M
    }
4118
4119
50.9k
    if (hdr->TL)
4120
84
        free(hdr->TL);
4121
50.9k
    if (hdr->TD_blk)
4122
48.5k
        cram_free_block(hdr->TD_blk);
4123
50.9k
    if (hdr->TD_hash)
4124
48.4k
        kh_destroy(m_s2i, hdr->TD_hash);
4125
50.9k
    if (hdr->TD_keys)
4126
48.4k
        string_pool_destroy(hdr->TD_keys);
4127
4128
50.9k
    free(hdr);
4129
50.9k
}
4130
4131
4132
/* ----------------------------------------------------------------------
4133
 * Slices and slice headers
4134
 */
4135
4136
40.6k
void cram_free_slice_header(cram_block_slice_hdr *hdr) {
4137
40.6k
    if (!hdr)
4138
0
        return;
4139
4140
40.6k
    if (hdr->block_content_ids)
4141
39.9k
        free(hdr->block_content_ids);
4142
4143
40.6k
    free(hdr);
4144
4145
40.6k
    return;
4146
40.6k
}
4147
4148
40.7k
void cram_free_slice(cram_slice *s) {
4149
40.7k
    if (!s)
4150
0
        return;
4151
4152
40.7k
    if (s->bl) {
4153
0
        free_bam_list(s->bl->bams, s->bl->nbams);
4154
0
        free(s->bl);
4155
0
    }
4156
4157
40.7k
    if (s->hdr_block)
4158
39.6k
        cram_free_block(s->hdr_block);
4159
4160
40.7k
    if (s->block) {
4161
39.9k
        int i;
4162
4163
39.9k
        if (s->hdr) {
4164
379k
            for (i = 0; i < s->hdr->num_blocks; i++) {
4165
339k
                if (i > 0 && s->block[i] == s->block[0])
4166
31.6k
                    continue;
4167
307k
                cram_free_block(s->block[i]);
4168
307k
            }
4169
39.9k
        }
4170
39.9k
        free(s->block);
4171
39.9k
    }
4172
4173
40.7k
    {
4174
        // Normally already copied into s->block[], but potentially still
4175
        // here if we error part way through cram_encode_slice.
4176
40.7k
        int i;
4177
129k
        for (i = 0; i < s->naux_block; i++)
4178
88.4k
            cram_free_block(s->aux_block[i]);
4179
40.7k
    }
4180
4181
40.7k
    if (s->block_by_id)
4182
81
        free(s->block_by_id);
4183
4184
40.7k
    if (s->hdr)
4185
40.6k
        cram_free_slice_header(s->hdr);
4186
4187
40.7k
    if (s->seqs_blk)
4188
40.5k
        cram_free_block(s->seqs_blk);
4189
4190
40.7k
    if (s->qual_blk)
4191
805
        cram_free_block(s->qual_blk);
4192
4193
40.7k
    if (s->name_blk)
4194
805
        cram_free_block(s->name_blk);
4195
4196
40.7k
    if (s->aux_blk)
4197
40.5k
        cram_free_block(s->aux_blk);
4198
4199
40.7k
    if (s->base_blk)
4200
805
        cram_free_block(s->base_blk);
4201
4202
40.7k
    if (s->soft_blk)
4203
805
        cram_free_block(s->soft_blk);
4204
4205
40.7k
    if (s->cigar)
4206
40.5k
        free(s->cigar);
4207
4208
40.7k
    if (s->crecs)
4209
40.5k
        free(s->crecs);
4210
4211
40.7k
    if (s->features)
4212
18.5k
        free(s->features);
4213
4214
40.7k
    if (s->TN)
4215
0
        free(s->TN);
4216
4217
40.7k
    if (s->pair_keys)
4218
40.4k
        string_pool_destroy(s->pair_keys);
4219
4220
40.7k
    if (s->pair[0])
4221
40.4k
        kh_destroy(m_s2i, s->pair[0]);
4222
40.7k
    if (s->pair[1])
4223
40.4k
        kh_destroy(m_s2i, s->pair[1]);
4224
4225
40.7k
    if (s->aux_block)
4226
36.7k
        free(s->aux_block);
4227
4228
40.7k
    free(s);
4229
40.7k
}
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
40.4k
cram_slice *cram_new_slice(enum cram_content_type type, int nrecs) {
4239
40.4k
    cram_slice *s = calloc(1, sizeof(*s));
4240
40.4k
    if (!s)
4241
0
        return NULL;
4242
4243
40.4k
    if (!(s->hdr = (cram_block_slice_hdr *)calloc(1, sizeof(*s->hdr))))
4244
0
        goto err;
4245
40.4k
    s->hdr->content_type = type;
4246
4247
40.4k
    s->hdr_block = NULL;
4248
40.4k
    s->block = NULL;
4249
40.4k
    s->block_by_id = NULL;
4250
40.4k
    s->last_apos = 0;
4251
40.4k
    if (!(s->crecs = hts_malloc_p(sizeof(*s->crecs), nrecs)))  goto err;
4252
40.4k
    s->cigar_alloc = 1024;
4253
40.4k
    if (!(s->cigar = hts_malloc_p(sizeof(*s->cigar), s->cigar_alloc))) goto err;
4254
40.4k
    s->ncigar = 0;
4255
4256
40.4k
    if (!(s->seqs_blk = cram_new_block(EXTERNAL, 0)))       goto err;
4257
40.4k
    if (!(s->qual_blk = cram_new_block(EXTERNAL, DS_QS)))   goto err;
4258
40.4k
    if (!(s->name_blk = cram_new_block(EXTERNAL, DS_RN)))   goto err;
4259
40.4k
    if (!(s->aux_blk  = cram_new_block(EXTERNAL, DS_aux)))  goto err;
4260
40.4k
    if (!(s->base_blk = cram_new_block(EXTERNAL, DS_IN)))   goto err;
4261
40.4k
    if (!(s->soft_blk = cram_new_block(EXTERNAL, DS_SC)))   goto err;
4262
4263
40.4k
    s->features = NULL;
4264
40.4k
    s->nfeatures = s->afeatures = 0;
4265
4266
40.4k
#ifndef TN_external
4267
40.4k
    s->TN = NULL;
4268
40.4k
    s->nTN = s->aTN = 0;
4269
40.4k
#endif
4270
4271
    // Volatile keys as we do realloc in dstring
4272
40.4k
    if (!(s->pair_keys = string_pool_create(8192))) goto err;
4273
40.4k
    if (!(s->pair[0] = kh_init(m_s2i)))             goto err;
4274
40.4k
    if (!(s->pair[1] = kh_init(m_s2i)))             goto err;
4275
4276
#ifdef BA_external
4277
    s->BA_len = 0;
4278
#endif
4279
4280
40.4k
    return s;
4281
4282
0
 err:
4283
0
    if (s)
4284
0
        cram_free_slice(s);
4285
4286
0
    return NULL;
4287
40.4k
}
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
285
cram_slice *cram_read_slice(cram_fd *fd) {
4301
285
    cram_block *b = cram_read_block(fd);
4302
285
    cram_slice *s = calloc(1, sizeof(*s));
4303
285
    int i, n, max_id, min_id;
4304
4305
285
    if (!b || !s)
4306
21
        goto err;
4307
4308
264
    s->hdr_block = b;
4309
264
    switch (b->content_type) {
4310
234
    case MAPPED_SLICE:
4311
258
    case UNMAPPED_SLICE:
4312
258
        if (!(s->hdr = cram_decode_slice_header(fd, b)))
4313
108
            goto err;
4314
150
        break;
4315
4316
150
    default:
4317
6
        hts_log_error("Unexpected block of type %s",
4318
6
                      cram_content_type2str(b->content_type));
4319
6
        goto err;
4320
264
    }
4321
4322
150
    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
150
    s->block = calloc(n = s->hdr->num_blocks, sizeof(*s->block));
4328
150
    if (!s->block)
4329
0
        goto err;
4330
4331
1.92k
    for (max_id = i = 0, min_id = INT_MAX; i < n; i++) {
4332
1.83k
        if (!(s->block[i] = cram_read_block(fd)))
4333
69
            goto err;
4334
4335
1.77k
        if (s->block[i]->content_type == EXTERNAL) {
4336
699
            if (max_id < s->block[i]->content_id)
4337
36
                max_id = s->block[i]->content_id;
4338
699
            if (min_id > s->block[i]->content_id)
4339
63
                min_id = s->block[i]->content_id;
4340
699
        }
4341
1.77k
    }
4342
4343
81
    if (!(s->block_by_id = calloc(512, sizeof(s->block[0]))))
4344
0
        goto err;
4345
4346
1.14k
    for (i = 0; i < n; i++) {
4347
1.06k
        if (s->block[i]->content_type != EXTERNAL)
4348
549
            continue;
4349
519
        uint32_t v = s->block[i]->content_id;
4350
519
        if (v >= 256)
4351
12
            v = 256 + v % 251;
4352
519
        s->block_by_id[v] = s->block[i];
4353
519
    }
4354
4355
    /* Initialise encoding/decoding tables */
4356
81
    s->cigar_alloc = 1024;
4357
81
    if (!(s->cigar = hts_malloc_p(sizeof(*s->cigar), s->cigar_alloc))) goto err;
4358
81
    s->ncigar = 0;
4359
4360
81
    if (!(s->seqs_blk = cram_new_block(EXTERNAL, 0)))      goto err;
4361
81
    if (!(s->qual_blk = cram_new_block(EXTERNAL, DS_QS)))  goto err;
4362
81
    if (!(s->name_blk = cram_new_block(EXTERNAL, DS_RN)))  goto err;
4363
81
    if (!(s->aux_blk  = cram_new_block(EXTERNAL, DS_aux))) goto err;
4364
81
    if (!(s->base_blk = cram_new_block(EXTERNAL, DS_IN)))  goto err;
4365
81
    if (!(s->soft_blk = cram_new_block(EXTERNAL, DS_SC)))  goto err;
4366
4367
81
    s->crecs = NULL;
4368
4369
81
    s->last_apos = s->hdr->ref_seq_start;
4370
81
    s->decode_md = fd->decode_md;
4371
4372
81
    return s;
4373
4374
204
 err:
4375
204
    if (b)
4376
183
        cram_free_block(b);
4377
204
    if (s) {
4378
204
        s->hdr_block = NULL;
4379
204
        cram_free_slice(s);
4380
204
    }
4381
204
    return NULL;
4382
81
}
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
9.53k
cram_file_def *cram_read_file_def(cram_fd *fd) {
4395
9.53k
    cram_file_def *def = malloc(sizeof(*def));
4396
9.53k
    if (!def)
4397
0
        return NULL;
4398
4399
9.53k
    if (26 != hread(fd->fp, &def->magic[0], 26)) {
4400
5
        free(def);
4401
5
        return NULL;
4402
5
    }
4403
4404
9.52k
    if (memcmp(def->magic, "CRAM", 4) != 0) {
4405
1
        free(def);
4406
1
        return NULL;
4407
1
    }
4408
4409
9.52k
    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
9.52k
    fd->first_container += 26;
4417
9.52k
    fd->curr_position = fd->first_container;
4418
9.52k
    fd->last_slice = 0;
4419
4420
9.52k
    return def;
4421
9.52k
}
4422
4423
/*
4424
 * Writes a cram_file_def structure to cram_fd.
4425
 * Returns 0 on success
4426
 *        -1 on failure
4427
 */
4428
7.98k
int cram_write_file_def(cram_fd *fd, cram_file_def *def) {
4429
7.98k
    return (hwrite(fd->fp, &def->magic[0], 26) == 26) ? 0 : -1;
4430
7.98k
}
4431
4432
18.1k
void cram_free_file_def(cram_file_def *def) {
4433
18.1k
    if (def) free(def);
4434
18.1k
}
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
9.52k
sam_hdr_t *cram_read_SAM_hdr(cram_fd *fd) {
4450
9.52k
    int32_t header_len;
4451
9.52k
    char *header;
4452
9.52k
    sam_hdr_t *hdr;
4453
4454
    /* 1.1 onwards stores the header in the first block of a container */
4455
9.52k
    if (CRAM_MAJOR_VERS(fd->version) == 1) {
4456
        /* Length */
4457
7.79k
        if (-1 == int32_decode(fd, &header_len))
4458
1
            return NULL;
4459
4460
7.79k
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
4461
7.79k
        if (header_len > FUZZ_ALLOC_LIMIT)
4462
2
            return NULL;
4463
7.79k
#endif
4464
4465
        /* Alloc and read */
4466
7.79k
        if (header_len < 0 || NULL == (header = malloc((size_t) header_len+1)))
4467
0
            return NULL;
4468
4469
7.79k
        if (header_len != hread(fd->fp, header, header_len)) {
4470
26
            free(header);
4471
26
            return NULL;
4472
26
        }
4473
7.77k
        header[header_len] = '\0';
4474
4475
7.77k
        fd->first_container += 4 + header_len;
4476
7.77k
    } else {
4477
1.72k
        cram_container *c = cram_read_container(fd);
4478
1.72k
        cram_block *b;
4479
1.72k
        int i;
4480
1.72k
        int64_t len;
4481
4482
1.72k
        if (!c)
4483
94
            return NULL;
4484
4485
1.63k
        fd->first_container += c->length + c->offset;
4486
1.63k
        fd->curr_position = fd->first_container;
4487
4488
1.63k
        if (c->num_blocks < 1) {
4489
48
            cram_free_container(c);
4490
48
            return NULL;
4491
48
        }
4492
4493
1.58k
        if (!(b = cram_read_block(fd))) {
4494
71
            cram_free_container(c);
4495
71
            return NULL;
4496
71
        }
4497
1.51k
        if (cram_uncompress_block(b) != 0) {
4498
1.15k
            cram_free_container(c);
4499
1.15k
            cram_free_block(b);
4500
1.15k
            return NULL;
4501
1.15k
        }
4502
4503
358
        len = b->comp_size + 2 + 4*(CRAM_MAJOR_VERS(fd->version) >= 3) +
4504
358
            fd->vv.varint_size(b->content_id) +
4505
358
            fd->vv.varint_size(b->uncomp_size) +
4506
358
            fd->vv.varint_size(b->comp_size);
4507
4508
        /* Extract header from 1st block */
4509
358
        if (-1 == int32_get_blk(b, &header_len) ||
4510
302
            header_len < 0 || /* Spec. says signed...  why? */
4511
293
            b->uncomp_size - 4 < header_len) {
4512
88
            cram_free_container(c);
4513
88
            cram_free_block(b);
4514
88
            return NULL;
4515
88
        }
4516
270
        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
270
        memcpy(header, BLOCK_END(b), header_len);
4522
270
        header[header_len] = '\0';
4523
270
        cram_free_block(b);
4524
4525
        /* Consume any remaining blocks */
4526
659
        for (i = 1; i < c->num_blocks; i++) {
4527
410
            if (!(b = cram_read_block(fd))) {
4528
21
                cram_free_container(c);
4529
21
                free(header);
4530
21
                return NULL;
4531
21
            }
4532
389
            len += b->comp_size + 2 + 4*(CRAM_MAJOR_VERS(fd->version) >= 3) +
4533
389
                fd->vv.varint_size(b->content_id) +
4534
389
                fd->vv.varint_size(b->uncomp_size) +
4535
389
                fd->vv.varint_size(b->comp_size);
4536
389
            cram_free_block(b);
4537
389
        }
4538
4539
249
        if (c->length > 0 && len > 0 && c->length > len) {
4540
            // Consume padding
4541
22
            char *pads = malloc(c->length - len);
4542
22
            if (!pads) {
4543
0
                cram_free_container(c);
4544
0
                free(header);
4545
0
                return NULL;
4546
0
            }
4547
4548
22
            if (c->length - len != hread(fd->fp, pads, c->length - len)) {
4549
13
                cram_free_container(c);
4550
13
                free(header);
4551
13
                free(pads);
4552
13
                return NULL;
4553
13
            }
4554
9
            free(pads);
4555
9
        }
4556
4557
236
        cram_free_container(c);
4558
236
    }
4559
4560
    /* Parse */
4561
8.00k
    hdr = sam_hdr_init();
4562
8.00k
    if (!hdr) {
4563
0
        free(header);
4564
0
        return NULL;
4565
0
    }
4566
4567
8.00k
    if (-1 == sam_hdr_add_lines(hdr, header, header_len)) {
4568
90
        free(header);
4569
90
        sam_hdr_destroy(hdr);
4570
90
        return NULL;
4571
90
    }
4572
4573
7.91k
    hdr->l_text = header_len;
4574
7.91k
    hdr->text = header;
4575
4576
7.91k
    return hdr;
4577
4578
8.00k
}
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
7.98k
int cram_write_SAM_hdr(cram_fd *fd, sam_hdr_t *hdr) {
4624
7.98k
    size_t header_len;
4625
7.98k
    int blank_block = (CRAM_MAJOR_VERS(fd->version) >= 3);
4626
4627
    /* Write CRAM MAGIC if not yet written. */
4628
7.98k
    if (fd->file_def->major_version == 0) {
4629
7.98k
        fd->file_def->major_version = CRAM_MAJOR_VERS(fd->version);
4630
7.98k
        fd->file_def->minor_version = CRAM_MINOR_VERS(fd->version);
4631
7.98k
        if (0 != cram_write_file_def(fd, fd->file_def))
4632
0
            return -1;
4633
7.98k
    }
4634
4635
    /* 1.0 requires an UNKNOWN read-group */
4636
7.98k
    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
7.98k
    if (-1 == refs_from_header(fd))
4644
0
        return -1;
4645
7.98k
    if (-1 == refs2id(fd->refs, fd->header))
4646
0
        return -1;
4647
4648
    /* Fix M5 strings */
4649
7.98k
    if (fd->refs && !fd->no_ref && fd->embed_ref <= 1) {
4650
7.98k
        int i;
4651
8.08k
        for (i = 0; i < hdr->hrecs->nref; i++) {
4652
2.74k
            sam_hrec_type_t *ty;
4653
2.74k
            char *ref;
4654
4655
2.74k
            if (!(ty = sam_hrecs_find_type_id(hdr->hrecs, "SQ", "SN", hdr->hrecs->ref[i].name)))
4656
0
                return -1;
4657
4658
2.74k
            if (!sam_hrecs_find_key(ty, "M5", NULL)) {
4659
2.64k
                char unsigned buf[16];
4660
2.64k
                char buf2[33];
4661
2.64k
                hts_pos_t rlen;
4662
2.64k
                hts_md5_context *md5;
4663
4664
2.64k
                if (!fd->refs ||
4665
2.64k
                    !fd->refs->ref_id ||
4666
2.64k
                    !fd->refs->ref_id[i]) {
4667
0
                    return -1;
4668
0
                }
4669
2.64k
                rlen = fd->refs->ref_id[i]->length;
4670
2.64k
                ref = cram_get_ref(fd, i, 1, rlen);
4671
2.64k
                if (NULL == ref) {
4672
2.64k
                    if (fd->embed_ref == -1) {
4673
                        // auto embed-ref
4674
2.64k
                        hts_log_warning("No M5 tags present and could not "
4675
2.64k
                                        "find reference");
4676
2.64k
                        hts_log_warning("Enabling embed_ref=2 option");
4677
2.64k
                        hts_log_warning("NOTE: the CRAM file will be bigger "
4678
2.64k
                                        "than using an external reference");
4679
2.64k
                        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
2.64k
                        fd->embed_ref = 2;
4683
2.64k
                        pthread_mutex_unlock(&fd->ref_lock);
4684
2.64k
                        break;
4685
2.64k
                    }
4686
0
                    return -1;
4687
2.64k
                }
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
98
            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
98
        }
4721
7.98k
    }
4722
4723
7.98k
    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
7.98k
    header_len = sam_hdr_length(hdr);
4732
7.98k
    if (header_len > INT32_MAX) {
4733
0
        hts_log_error("Header is too long for CRAM format");
4734
0
        return -1;
4735
0
    }
4736
7.98k
    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
7.98k
    } else {
4744
        /* Create block(s) inside a container */
4745
7.98k
        cram_block *b = cram_new_block(FILE_HEADER, 0);
4746
7.98k
        cram_container *c = cram_new_container(0, 0);
4747
7.98k
        int padded_length;
4748
7.98k
        char *pads;
4749
7.98k
        int is_cram_3 = (CRAM_MAJOR_VERS(fd->version) >= 3);
4750
4751
7.98k
        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
7.98k
        if (int32_put_blk(b, header_len) < 0)
4758
0
            return -1;
4759
7.98k
        if (header_len)
4760
4.26k
            BLOCK_APPEND(b, sam_hdr_str(hdr), header_len);
4761
7.98k
        BLOCK_UPLEN(b);
4762
4763
        // Compress header block if V3.0 and above
4764
7.98k
        if (CRAM_MAJOR_VERS(fd->version) >= 3)
4765
7.98k
            if (cram_compress_block(fd, b, NULL, -1, -1) < 0)
4766
0
                return -1;
4767
4768
7.98k
        if (blank_block) {
4769
7.98k
            c->length = b->comp_size + 2 + 4*is_cram_3 +
4770
7.98k
                fd->vv.varint_size(b->content_id)   +
4771
7.98k
                fd->vv.varint_size(b->uncomp_size)  +
4772
7.98k
                fd->vv.varint_size(b->comp_size);
4773
4774
7.98k
            c->num_blocks = 2;
4775
7.98k
            c->num_landmarks = 2;
4776
7.98k
            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
7.98k
            c->landmark[0] = 0;
4782
7.98k
            c->landmark[1] = c->length;
4783
4784
            // Plus extra storage for uncompressed secondary blank block
4785
7.98k
            padded_length = MIN(c->length*.5, 10000);
4786
7.98k
            c->length += padded_length + 2 + 4*is_cram_3 +
4787
7.98k
                fd->vv.varint_size(b->content_id) +
4788
7.98k
                fd->vv.varint_size(padded_length)*2;
4789
7.98k
        } 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
7.98k
        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
7.98k
        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
7.98k
        if (blank_block) {
4828
7.98k
            BLOCK_RESIZE(b, padded_length);
4829
7.98k
            memset(BLOCK_DATA(b), 0, padded_length);
4830
7.98k
            BLOCK_SIZE(b) = padded_length;
4831
7.98k
            BLOCK_UPLEN(b);
4832
7.98k
            b->method = RAW;
4833
7.98k
            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
7.98k
        }
4839
4840
7.98k
        cram_free_block(b);
4841
7.98k
        cram_free_container(c);
4842
7.98k
    }
4843
4844
7.98k
    if (0 != hflush(fd->fp))
4845
0
        return -1;
4846
4847
7.98k
    RP("=== Finishing saving header ===\n");
4848
4849
7.98k
    return 0;
4850
4851
0
 block_err:
4852
0
    return -1;
4853
7.98k
}
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
18.1k
static void cram_init_varint(varint_vec *vv, int version) {
4869
18.1k
    vv->varint_get32 = safe_itf8_get;
4870
18.1k
    vv->varint_get32s = safe_itf8_get;
4871
18.1k
    vv->varint_get64 = safe_ltf8_get;
4872
18.1k
    vv->varint_get64s = safe_ltf8_get;
4873
18.1k
    vv->varint_put32 = safe_itf8_put;
4874
18.1k
    vv->varint_put32s = safe_itf8_put;
4875
18.1k
    vv->varint_put64 = safe_ltf8_put;
4876
18.1k
    vv->varint_put64s = safe_ltf8_put;
4877
18.1k
    vv->varint_put32_blk = itf8_put_blk;
4878
18.1k
    vv->varint_put32s_blk = itf8_put_blk;
4879
18.1k
    vv->varint_put64_blk = ltf8_put_blk;
4880
18.1k
    vv->varint_put64s_blk = ltf8_put_blk;
4881
18.1k
    vv->varint_size = itf8_size;
4882
18.1k
    vv->varint_decode32_crc = itf8_decode_crc;
4883
18.1k
    vv->varint_decode32s_crc = itf8_decode_crc;
4884
18.1k
    vv->varint_decode64_crc = ltf8_decode_crc;
4885
18.1k
}
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
18.1k
static void cram_init_tables(cram_fd *fd) {
4893
18.1k
    int i;
4894
4895
18.1k
    memset(fd->L1, 4, 256);
4896
18.1k
    fd->L1['A'] = 0; fd->L1['a'] = 0;
4897
18.1k
    fd->L1['C'] = 1; fd->L1['c'] = 1;
4898
18.1k
    fd->L1['G'] = 2; fd->L1['g'] = 2;
4899
18.1k
    fd->L1['T'] = 3; fd->L1['t'] = 3;
4900
4901
18.1k
    memset(fd->L2, 5, 256);
4902
18.1k
    fd->L2['A'] = 0; fd->L2['a'] = 0;
4903
18.1k
    fd->L2['C'] = 1; fd->L2['c'] = 1;
4904
18.1k
    fd->L2['G'] = 2; fd->L2['g'] = 2;
4905
18.1k
    fd->L2['T'] = 3; fd->L2['t'] = 3;
4906
18.1k
    fd->L2['N'] = 4; fd->L2['n'] = 4;
4907
4908
18.1k
    if (CRAM_MAJOR_VERS(fd->version) == 1) {
4909
4.00M
        for (i = 0; i < 0x200; i++) {
4910
3.99M
            int f = 0;
4911
4912
3.99M
            if (i & CRAM_FPAIRED)      f |= BAM_FPAIRED;
4913
3.99M
            if (i & CRAM_FPROPER_PAIR) f |= BAM_FPROPER_PAIR;
4914
3.99M
            if (i & CRAM_FUNMAP)       f |= BAM_FUNMAP;
4915
3.99M
            if (i & CRAM_FREVERSE)     f |= BAM_FREVERSE;
4916
3.99M
            if (i & CRAM_FREAD1)       f |= BAM_FREAD1;
4917
3.99M
            if (i & CRAM_FREAD2)       f |= BAM_FREAD2;
4918
3.99M
            if (i & CRAM_FSECONDARY)   f |= BAM_FSECONDARY;
4919
3.99M
            if (i & CRAM_FQCFAIL)      f |= BAM_FQCFAIL;
4920
3.99M
            if (i & CRAM_FDUP)         f |= BAM_FDUP;
4921
4922
3.99M
            fd->bam_flag_swap[i]  = f;
4923
3.99M
        }
4924
4925
31.9M
        for (i = 0; i < 0x1000; i++) {
4926
31.9M
            int g = 0;
4927
4928
31.9M
            if (i & BAM_FPAIRED)           g |= CRAM_FPAIRED;
4929
31.9M
            if (i & BAM_FPROPER_PAIR)  g |= CRAM_FPROPER_PAIR;
4930
31.9M
            if (i & BAM_FUNMAP)        g |= CRAM_FUNMAP;
4931
31.9M
            if (i & BAM_FREVERSE)      g |= CRAM_FREVERSE;
4932
31.9M
            if (i & BAM_FREAD1)        g |= CRAM_FREAD1;
4933
31.9M
            if (i & BAM_FREAD2)        g |= CRAM_FREAD2;
4934
31.9M
            if (i & BAM_FSECONDARY)    g |= CRAM_FSECONDARY;
4935
31.9M
            if (i & BAM_FQCFAIL)       g |= CRAM_FQCFAIL;
4936
31.9M
            if (i & BAM_FDUP)          g |= CRAM_FDUP;
4937
4938
31.9M
            fd->cram_flag_swap[i] = g;
4939
31.9M
        }
4940
10.3k
    } else {
4941
        /* NOP */
4942
42.2M
        for (i = 0; i < 0x1000; i++)
4943
42.2M
            fd->bam_flag_swap[i] = i;
4944
42.2M
        for (i = 0; i < 0x1000; i++)
4945
42.2M
            fd->cram_flag_swap[i] = i;
4946
10.3k
    }
4947
4948
18.1k
    memset(fd->cram_sub_matrix, 4, 32*32);
4949
597k
    for (i = 0; i < 32; i++) {
4950
579k
        fd->cram_sub_matrix[i]['A'&0x1f]=0;
4951
579k
        fd->cram_sub_matrix[i]['C'&0x1f]=1;
4952
579k
        fd->cram_sub_matrix[i]['G'&0x1f]=2;
4953
579k
        fd->cram_sub_matrix[i]['T'&0x1f]=3;
4954
579k
        fd->cram_sub_matrix[i]['N'&0x1f]=4;
4955
579k
    }
4956
108k
    for (i = 0; i < 20; i+=4) {
4957
90.5k
        int j;
4958
1.90M
        for (j = 0; j < 20; j++) {
4959
1.81M
            fd->cram_sub_matrix["ACGTN"[i>>2]&0x1f][j]=3;
4960
1.81M
            fd->cram_sub_matrix["ACGTN"[i>>2]&0x1f][j]=3;
4961
1.81M
            fd->cram_sub_matrix["ACGTN"[i>>2]&0x1f][j]=3;
4962
1.81M
            fd->cram_sub_matrix["ACGTN"[i>>2]&0x1f][j]=3;
4963
1.81M
        }
4964
90.5k
        fd->cram_sub_matrix["ACGTN"[i>>2]&0x1f][CRAM_SUBST_MATRIX[i+0]&0x1f]=0;
4965
90.5k
        fd->cram_sub_matrix["ACGTN"[i>>2]&0x1f][CRAM_SUBST_MATRIX[i+1]&0x1f]=1;
4966
90.5k
        fd->cram_sub_matrix["ACGTN"[i>>2]&0x1f][CRAM_SUBST_MATRIX[i+2]&0x1f]=2;
4967
90.5k
        fd->cram_sub_matrix["ACGTN"[i>>2]&0x1f][CRAM_SUBST_MATRIX[i+3]&0x1f]=3;
4968
90.5k
    }
4969
4970
18.1k
    cram_init_varint(&fd->vv, CRAM_MAJOR_VERS(fd->version));
4971
18.1k
}
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
18.1k
cram_fd *cram_dopen(hFILE *fp, const char *filename, const char *mode) {
5010
18.1k
    int i;
5011
18.1k
    const char *cp;
5012
18.1k
    cram_fd *fd = calloc(1, sizeof(*fd));
5013
18.1k
    if (!fd)
5014
0
        return NULL;
5015
5016
18.1k
    fd->level = CRAM_DEFAULT_LEVEL;
5017
54.3k
    for (i = 0; mode[i]; i++) {
5018
36.2k
        if (mode[i] >= '0' && mode[i] <= '9') {
5019
0
            fd->level = mode[i] - '0';
5020
0
            break;
5021
0
        }
5022
36.2k
    }
5023
5024
18.1k
    fd->fp = fp;
5025
18.1k
    fd->mode = *mode;
5026
18.1k
    fd->first_container = 0;
5027
18.1k
    fd->curr_position = 0;
5028
5029
18.1k
    if (fd->mode == 'r') {
5030
        /* Reader */
5031
5032
9.53k
        if (!(fd->file_def = cram_read_file_def(fd)))
5033
7
            goto err;
5034
5035
9.52k
        fd->version = fd->file_def->major_version * 256 +
5036
9.52k
            fd->file_def->minor_version;
5037
5038
9.52k
        cram_init_tables(fd);
5039
5040
9.52k
        if (!(fd->header = cram_read_SAM_hdr(fd))) {
5041
1.61k
            cram_free_file_def(fd->file_def);
5042
1.61k
            goto err;
5043
1.61k
        }
5044
5045
9.52k
    } else {
5046
        /* Writer */
5047
8.58k
        cram_file_def *def = calloc(1, sizeof(*def));
5048
8.58k
        if (!def)
5049
0
            return NULL;
5050
5051
8.58k
        fd->file_def = def;
5052
5053
8.58k
        def->magic[0] = 'C';
5054
8.58k
        def->magic[1] = 'R';
5055
8.58k
        def->magic[2] = 'A';
5056
8.58k
        def->magic[3] = 'M';
5057
8.58k
        def->major_version = 0; // Indicator to write file def later.
5058
8.58k
        def->minor_version = 0;
5059
8.58k
        memset(def->file_id, 0, 20);
5060
8.58k
        strncpy(def->file_id, filename, 20);
5061
5062
8.58k
        fd->version = major_version * 256 + minor_version;
5063
8.58k
        cram_init_tables(fd);
5064
5065
        /* SAM header written later along with this file_def */
5066
8.58k
    }
5067
5068
16.5k
    fd->prefix = strdup((cp = strrchr(filename, '/')) ? cp+1 : filename);
5069
16.5k
    if (!fd->prefix)
5070
0
        goto err;
5071
16.5k
    fd->first_base = fd->last_base = -1;
5072
16.5k
    fd->record_counter = 0;
5073
5074
16.5k
    fd->ctr = NULL;
5075
16.5k
    fd->ctr_mt = NULL;
5076
16.5k
    fd->refs  = refs_create();
5077
16.5k
    if (!fd->refs)
5078
0
        goto err;
5079
16.5k
    fd->ref_id = -2;
5080
16.5k
    fd->ref = NULL;
5081
5082
16.5k
    fd->decode_md = 0;
5083
16.5k
    fd->seqs_per_slice = SEQS_PER_SLICE;
5084
16.5k
    fd->bases_per_slice = BASES_PER_SLICE;
5085
16.5k
    fd->slices_per_container = SLICE_PER_CNT;
5086
16.5k
    fd->embed_ref = -1; // automatic selection
5087
16.5k
    fd->no_ref = 0;
5088
16.5k
    fd->no_ref_counter = 0;
5089
16.5k
    fd->ap_delta = 0;
5090
16.5k
    fd->ignore_md5 = 0;
5091
16.5k
    fd->lossy_read_names = 0;
5092
16.5k
    fd->use_bz2 = 0;
5093
16.5k
    fd->use_rans = (CRAM_MAJOR_VERS(fd->version) >= 3);
5094
16.5k
    fd->use_tok = (CRAM_MAJOR_VERS(fd->version) >= 3) && (CRAM_MINOR_VERS(fd->version) >= 1);
5095
16.5k
    fd->use_lzma = 0;
5096
16.5k
    fd->multi_seq = -1;
5097
16.5k
    fd->multi_seq_user = -1;
5098
16.5k
    fd->unsorted   = 0;
5099
16.5k
    fd->shared_ref = 0;
5100
16.5k
    fd->store_md = 0;
5101
16.5k
    fd->store_nm = 0;
5102
16.5k
    fd->last_RI_count = 0;
5103
5104
16.5k
    fd->index       = NULL;
5105
16.5k
    fd->own_pool    = 0;
5106
16.5k
    fd->pool        = NULL;
5107
16.5k
    fd->rqueue      = NULL;
5108
16.5k
    fd->job_pending = NULL;
5109
16.5k
    fd->ooc         = 0;
5110
16.5k
    fd->required_fields = INT_MAX;
5111
5112
16.5k
    pthread_mutex_init(&fd->metrics_lock, NULL);
5113
16.5k
    pthread_mutex_init(&fd->ref_lock, NULL);
5114
16.5k
    pthread_mutex_init(&fd->range_lock, NULL);
5115
16.5k
    pthread_mutex_init(&fd->bam_list_lock, NULL);
5116
5117
792k
    for (i = 0; i < DS_END; i++) {
5118
775k
        fd->m[i] = cram_new_metrics();
5119
775k
        if (!fd->m[i])
5120
0
            goto err;
5121
775k
    }
5122
5123
16.5k
    if (!(fd->tags_used = kh_init(m_metrics)))
5124
0
        goto err;
5125
5126
16.5k
    fd->range.refid = -2; // no ref.
5127
16.5k
    fd->eof = 1;          // See samtools issue #150
5128
16.5k
    fd->ref_fn = NULL;
5129
5130
16.5k
    fd->bl = NULL;
5131
5132
    /* Initialise dummy refs from the @SQ headers */
5133
16.5k
    if (-1 == refs_from_header(fd))
5134
0
        goto err;
5135
5136
16.5k
    return fd;
5137
5138
1.61k
 err:
5139
1.61k
    if (fd)
5140
1.61k
        free(fd);
5141
5142
1.61k
    return NULL;
5143
16.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
7.74k
int cram_write_eof_block(cram_fd *fd) {
5195
    // EOF block is a container with special values to aid detection
5196
7.74k
    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
7.74k
        cram_container c;
5207
7.74k
        memset(&c, 0, sizeof(c));
5208
7.74k
        c.ref_seq_id = -1;
5209
7.74k
        c.ref_seq_start = 0x454f46; // "EOF"
5210
7.74k
        c.ref_seq_span = 0;
5211
7.74k
        c.record_counter = 0;
5212
7.74k
        c.num_bases = 0;
5213
7.74k
        c.num_blocks = 1;
5214
7.74k
        int32_t land[1] = {0};
5215
7.74k
        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
7.74k
        cram_block_compression_hdr ch;
5228
7.74k
        memset(&ch, 0, sizeof(ch));
5229
7.74k
        c.comp_hdr_block = cram_encode_compression_header(fd, &c, &ch, 0);
5230
5231
7.74k
        c.length = c.comp_hdr_block->byte            // Landmark[0]
5232
7.74k
            + 5                                      // block struct
5233
7.74k
            + 4*(CRAM_MAJOR_VERS(fd->version) >= 3); // CRC
5234
7.74k
        if (cram_write_container(fd, &c) < 0 ||
5235
7.74k
            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
7.74k
        if (ch.preservation_map)
5241
0
            kh_destroy(map, ch.preservation_map);
5242
7.74k
        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
7.74k
    }
5260
5261
7.74k
    return 0;
5262
7.74k
}
5263
5264
/*
5265
 * Closes a CRAM file.
5266
 * Returns 0 on success
5267
 *        -1 on failure
5268
 */
5269
16.5k
int cram_close(cram_fd *fd) {
5270
16.5k
    bam_list *bl, *next;
5271
16.5k
    int i, ret = 0;
5272
5273
16.5k
    if (!fd)
5274
0
        return -1;
5275
5276
16.5k
    if (fd->mode == 'w' && fd->ctr) {
5277
4.14k
        if(fd->ctr->slice)
5278
4.14k
            cram_update_curr_slice(fd->ctr, fd->version);
5279
5280
4.14k
        if (-1 == cram_flush_container_mt(fd, fd->ctr))
5281
847
            ret = -1;
5282
4.14k
    }
5283
5284
16.5k
    if (fd->mode != 'w')
5285
7.91k
        cram_drain_rqueue(fd);
5286
5287
16.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
16.5k
    pthread_mutex_destroy(&fd->metrics_lock);
5302
16.5k
    pthread_mutex_destroy(&fd->ref_lock);
5303
16.5k
    pthread_mutex_destroy(&fd->range_lock);
5304
16.5k
    pthread_mutex_destroy(&fd->bam_list_lock);
5305
5306
16.5k
    if (ret == 0 && fd->mode == 'w') {
5307
        /* Write EOF block */
5308
7.74k
        if (0 != cram_write_eof_block(fd))
5309
0
            ret = -1;
5310
7.74k
    }
5311
5312
20.1k
    for (bl = fd->bl; bl; bl = next) {
5313
3.60k
        next = bl->next;
5314
3.60k
        free_bam_list(bl->bams, bl->nbams);
5315
3.60k
        free(bl);
5316
3.60k
    }
5317
5318
16.5k
    if (hclose(fd->fp) != 0)
5319
0
        ret = -1;
5320
5321
16.5k
    if (fd->file_def)
5322
16.5k
        cram_free_file_def(fd->file_def);
5323
5324
16.5k
    if (fd->header)
5325
16.0k
        sam_hdr_destroy(fd->header);
5326
5327
16.5k
    free(fd->prefix);
5328
5329
16.5k
    if (fd->ctr)
5330
9.50k
        cram_free_container(fd->ctr);
5331
5332
16.5k
    if (fd->ctr_mt && fd->ctr_mt != fd->ctr)
5333
185
        cram_free_container(fd->ctr_mt);
5334
5335
16.5k
    if (fd->refs)
5336
16.5k
        refs_free(fd->refs);
5337
16.5k
    if (fd->ref_free)
5338
0
        free(fd->ref_free);
5339
5340
792k
    for (i = 0; i < DS_END; i++)
5341
775k
        if (fd->m[i])
5342
775k
            free(fd->m[i]);
5343
5344
16.5k
    if (fd->tags_used) {
5345
16.5k
        khint_t k;
5346
5347
32.0k
        for (k = kh_begin(fd->tags_used); k != kh_end(fd->tags_used); k++) {
5348
15.5k
            if (kh_exist(fd->tags_used, k))
5349
7.36k
                free(kh_val(fd->tags_used, k));
5350
15.5k
        }
5351
5352
16.5k
        kh_destroy(m_metrics, fd->tags_used);
5353
16.5k
    }
5354
5355
16.5k
    if (fd->index)
5356
0
        cram_index_free(fd);
5357
5358
16.5k
    if (fd->own_pool && fd->pool)
5359
0
        hts_tpool_destroy(fd->pool);
5360
5361
16.5k
    if (fd->idxfp)
5362
0
        if (bgzf_close(fd->idxfp) < 0)
5363
0
            ret = -1;
5364
5365
16.5k
    free(fd);
5366
5367
16.5k
    return ret;
5368
16.5k
}
5369
5370
/*
5371
 * Returns 1 if we hit an EOF while reading.
5372
 */
5373
13.8k
int cram_eof(cram_fd *fd) {
5374
13.8k
    return fd->eof;
5375
13.8k
}
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
7.91k
int cram_set_option(cram_fd *fd, enum hts_fmt_option opt, ...) {
5386
7.91k
    int r;
5387
7.91k
    va_list args;
5388
5389
7.91k
    va_start(args, opt);
5390
7.91k
    r = cram_set_voption(fd, opt, args);
5391
7.91k
    va_end(args);
5392
5393
7.91k
    return r;
5394
7.91k
}
5395
5396
// Check valid range for options.
5397
#define CHECK_RANGE(v,min,max)                  \
5398
7.91k
    do {                                        \
5399
7.91k
        int val = (v);                          \
5400
7.91k
        if((val) < (min) || (val) > (max)) {    \
5401
7.91k
            errno = ERANGE;                     \
5402
7.91k
            return -1;                          \
5403
7.91k
        }                                       \
5404
7.91k
    } 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
7.91k
int cram_set_voption(cram_fd *fd, enum hts_fmt_option opt, va_list args) {
5414
7.91k
    refs_t *refs;
5415
5416
7.91k
    if (!fd) {
5417
0
        errno = EBADF;
5418
0
        return -1;
5419
0
    }
5420
5421
7.91k
    switch (opt) {
5422
7.91k
    case CRAM_OPT_DECODE_MD:
5423
7.91k
        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)*1.3+1,
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
7.91k
    }
5673
5674
0
    return 0;
5675
7.91k
}
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
}