Coverage Report

Created: 2026-02-26 07:02

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/hdf5/src/H5FDonion_header.c
Line
Count
Source
1
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2
 * Copyright by The HDF Group.                                               *
3
 * All rights reserved.                                                      *
4
 *                                                                           *
5
 * This file is part of HDF5.  The full HDF5 copyright notice, including     *
6
 * terms governing use, modification, and redistribution, is contained in    *
7
 * the LICENSE file, which can be found at the root of the source code       *
8
 * distribution tree, or in https://www.hdfgroup.org/licenses.               *
9
 * If you do not have access to either file, you may request a copy from     *
10
 * help@hdfgroup.org.                                                        *
11
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
12
13
/*
14
 * Onion Virtual File Driver (VFD)
15
 *
16
 * Purpose:     Code for the onion file's header
17
 */
18
19
#include "H5FDmodule.h" /* This source code file is part of the H5FD module */
20
21
#include "H5private.h"      /* Generic Functions                        */
22
#include "H5Eprivate.h"     /* Error handling                           */
23
#include "H5FDpkg.h"        /* File drivers                             */
24
#include "H5FDonion_priv.h" /* Onion file driver internals              */
25
#include "H5MMprivate.h"    /* Memory management                        */
26
27
/*-----------------------------------------------------------------------------
28
 * Function:    H5FD_ingest_header
29
 *
30
 * Purpose:     Read and decode the history header information from `raw_file`
31
 *              at `addr`, and store the decoded information in the structure
32
 *              at `hdr_out`.
33
 *
34
 * Return:      SUCCEED/FAIL
35
 *-----------------------------------------------------------------------------
36
 */
37
herr_t
38
H5FD__onion_ingest_header(H5FD_onion_header_t *hdr_out, H5FD_t *raw_file, haddr_t addr)
39
0
{
40
0
    unsigned char *buf       = NULL;
41
0
    herr_t         ret_value = SUCCEED;
42
0
    haddr_t        size      = (haddr_t)H5FD_ONION_ENCODED_SIZE_HEADER;
43
0
    uint32_t       sum       = 0;
44
45
0
    FUNC_ENTER_PACKAGE
46
47
0
    if (H5FD_get_eof(raw_file, H5FD_MEM_DRAW) < (addr + size))
48
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "header indicates history beyond EOF");
49
50
0
    if (NULL == (buf = H5MM_malloc(sizeof(char) * size)))
51
0
        HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, FAIL, "can't allocate buffer space");
52
53
0
    if (H5FD_set_eoa(raw_file, H5FD_MEM_DRAW, (addr + size)) < 0)
54
0
        HGOTO_ERROR(H5E_VFL, H5E_CANTSET, FAIL, "can't modify EOA");
55
56
0
    if (H5FD_read(raw_file, H5FD_MEM_DRAW, addr, size, buf) < 0)
57
0
        HGOTO_ERROR(H5E_VFL, H5E_READERROR, FAIL, "can't read history header from file");
58
59
0
    if (H5FD__onion_header_decode(buf, hdr_out) == 0)
60
0
        HGOTO_ERROR(H5E_VFL, H5E_CANTDECODE, FAIL, "can't decode history header");
61
62
0
    sum = H5_checksum_fletcher32(buf, size - 4);
63
0
    if (hdr_out->checksum != sum)
64
0
        HGOTO_ERROR(H5E_VFL, H5E_BADVALUE, FAIL, "checksum mismatch between buffer and stored");
65
66
0
done:
67
0
    H5MM_xfree(buf);
68
69
0
    FUNC_LEAVE_NOAPI(ret_value)
70
0
} /* end H5FD__onion_ingest_header() */
71
72
/*-------------------------------------------------------------------------
73
 * Function:    H5FD__onion_write_header
74
 *
75
 * Purpose:     Write in-memory history header to appropriate backing file.
76
 *              Overwrites existing header data.
77
 *
78
 * Return:      SUCCEED/FAIL
79
 *-------------------------------------------------------------------------
80
 */
81
herr_t
82
H5FD__onion_write_header(H5FD_onion_header_t *header, H5FD_t *file)
83
0
{
84
0
    uint32_t       sum       = 0; /* Not used, but required by the encoder */
85
0
    uint64_t       size      = 0;
86
0
    unsigned char *buf       = NULL;
87
0
    herr_t         ret_value = SUCCEED;
88
89
0
    FUNC_ENTER_PACKAGE
90
91
0
    if (NULL == (buf = H5MM_malloc(H5FD_ONION_ENCODED_SIZE_HEADER)))
92
0
        HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, FAIL, "can't allocate buffer for updated history header");
93
94
0
    if (0 == (size = H5FD__onion_header_encode(header, buf, &sum)))
95
0
        HGOTO_ERROR(H5E_VFL, H5E_BADVALUE, FAIL, "problem encoding updated history header");
96
97
0
    if (H5FD_write(file, H5FD_MEM_DRAW, 0, (haddr_t)size, buf) < 0)
98
0
        HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, FAIL, "can't write updated history header");
99
100
0
done:
101
0
    H5MM_xfree(buf);
102
103
0
    FUNC_LEAVE_NOAPI(ret_value)
104
0
} /* end H5FD__onion_write_header()*/
105
106
/*-----------------------------------------------------------------------------
107
 * Function:    H5FD__onion_header_decode
108
 *
109
 * Purpose:     Attempt to read a buffer and store it as a history-header
110
 *              structure.
111
 *
112
 *              Implementation must correspond with
113
 *              H5FD__onion_header_encode().
114
 *
115
 * Return:      Success:    Number of bytes read from buffer
116
 *              Failure:    0
117
 *-----------------------------------------------------------------------------
118
 */
119
size_t
120
H5FD__onion_header_decode(unsigned char *buf, H5FD_onion_header_t *header)
121
0
{
122
0
    uint32_t       ui32      = 0;
123
0
    uint32_t       sum       = 0;
124
0
    uint64_t       ui64      = 0;
125
0
    uint8_t       *ui8p      = NULL;
126
0
    unsigned char *ptr       = NULL;
127
0
    size_t         ret_value = 0;
128
129
0
    FUNC_ENTER_PACKAGE
130
131
0
    assert(buf != NULL);
132
0
    assert(header != NULL);
133
0
    assert(H5FD_ONION_HEADER_VERSION_CURR == header->version);
134
135
0
    if (strncmp((const char *)buf, H5FD_ONION_HEADER_SIGNATURE, 4))
136
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, 0, "invalid header signature");
137
138
0
    if (buf[4] != H5FD_ONION_HEADER_VERSION_CURR)
139
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, 0, "invalid header version");
140
141
0
    ptr  = buf + 5;
142
0
    ui32 = 0;
143
0
    H5MM_memcpy(&ui32, ptr, 3);
144
0
    ui8p = (uint8_t *)&ui32;
145
0
    UINT32DECODE(ui8p, header->flags);
146
0
    ptr += 3;
147
148
0
    H5MM_memcpy(&ui32, ptr, 4);
149
0
    ui8p = (uint8_t *)&ui32;
150
0
    UINT32DECODE(ui8p, header->page_size);
151
0
    ptr += 4;
152
153
0
    H5MM_memcpy(&ui64, ptr, 8);
154
0
    ui8p = (uint8_t *)&ui64;
155
0
    UINT32DECODE(ui8p, header->origin_eof);
156
0
    ptr += 8;
157
158
0
    H5MM_memcpy(&ui64, ptr, 8);
159
0
    ui8p = (uint8_t *)&ui64;
160
0
    UINT32DECODE(ui8p, header->history_addr);
161
0
    ptr += 8;
162
163
0
    H5MM_memcpy(&ui64, ptr, 8);
164
0
    ui8p = (uint8_t *)&ui64;
165
0
    UINT32DECODE(ui8p, header->history_size);
166
0
    ptr += 8;
167
168
0
    sum = H5_checksum_fletcher32(buf, (size_t)(ptr - buf));
169
170
0
    H5MM_memcpy(&ui32, ptr, 4);
171
0
    ui8p = (uint8_t *)&ui32;
172
0
    UINT32DECODE(ui8p, header->checksum);
173
0
    ptr += 4;
174
175
0
    if (sum != header->checksum)
176
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, 0, "checksum mismatch");
177
178
0
    ret_value = (size_t)(ptr - buf);
179
180
0
done:
181
0
    FUNC_LEAVE_NOAPI(ret_value)
182
0
} /* end H5FD__onion_header_decode() */
183
184
/*-----------------------------------------------------------------------------
185
 * Function:    H5FD__onion_header_encode
186
 *
187
 * Purpose:     Write history-header structure to the given buffer.
188
 *              All multi-byte elements are stored in little-endian word order.
189
 *
190
 *              Implementation must correspond with
191
 *              H5FD__onion_header_decode().
192
 *
193
 *              The destination buffer must be sufficiently large to hold the
194
 *              encoded contents (H5FD_ONION_ENCODED_SIZE_HEADER).
195
 *
196
 * Return:      Number of bytes written to buffer.
197
 *              The checksum of the generated buffer contents (excluding the
198
 *              checksum itself) is stored in the pointer `checksum`).
199
 *-----------------------------------------------------------------------------
200
 */
201
size_t
202
H5FD__onion_header_encode(H5FD_onion_header_t *header, unsigned char *buf, uint32_t *checksum /*out*/)
203
0
{
204
0
    unsigned char *ptr       = buf;
205
0
    size_t         ret_value = 0;
206
207
0
    FUNC_ENTER_PACKAGE_NOERR
208
209
0
    assert(buf != NULL);
210
0
    assert(checksum != NULL);
211
0
    assert(header != NULL);
212
0
    assert(H5FD_ONION_HEADER_VERSION_CURR == header->version);
213
0
    assert(0 == (header->flags & 0xFF000000)); /* max three bits long */
214
215
0
    H5MM_memcpy(ptr, H5FD_ONION_HEADER_SIGNATURE, 4);
216
0
    ptr += 4;
217
0
    H5MM_memcpy(ptr, (unsigned char *)&header->version, 1);
218
0
    ptr += 1;
219
0
    UINT32ENCODE(ptr, header->flags);
220
0
    ptr -= 1; /* truncate to three bytes */
221
0
    UINT32ENCODE(ptr, header->page_size);
222
0
    UINT64ENCODE(ptr, header->origin_eof);
223
0
    UINT64ENCODE(ptr, header->history_addr);
224
0
    UINT64ENCODE(ptr, header->history_size);
225
0
    *checksum = H5_checksum_fletcher32(buf, (size_t)(ptr - buf));
226
0
    UINT32ENCODE(ptr, *checksum);
227
0
    ret_value = (size_t)(ptr - buf);
228
229
0
    FUNC_LEAVE_NOAPI(ret_value)
230
0
} /* end H5FD__onion_header_encode() */