Coverage Report

Created: 2025-11-17 06:13

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/hdf5/src/H5Omtime.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
 * Purpose:         The object modification time message
15
 */
16
17
#include "H5Omodule.h" /* This source code file is part of the H5O module */
18
19
#include "H5private.h"   /* Generic Functions     */
20
#include "H5Eprivate.h"  /* Error handling        */
21
#include "H5FLprivate.h" /* Free lists                           */
22
#include "H5Opkg.h"      /* Object headers      */
23
24
static void  *H5O__mtime_new_decode(H5F_t *f, H5O_t *open_oh, unsigned mesg_flags, unsigned *ioflags,
25
                                    size_t p_size, const uint8_t *p);
26
static herr_t H5O__mtime_new_encode(H5F_t *f, bool disable_shared, size_t H5_ATTR_UNUSED p_size, uint8_t *p,
27
                                    const void *_mesg);
28
static size_t H5O__mtime_new_size(const H5F_t *f, bool disable_shared, const void *_mesg);
29
30
static void  *H5O__mtime_decode(H5F_t *f, H5O_t *open_oh, unsigned mesg_flags, unsigned *ioflags,
31
                                size_t p_size, const uint8_t *p);
32
static herr_t H5O__mtime_encode(H5F_t *f, bool disable_shared, size_t p_size, uint8_t *p, const void *_mesg);
33
static void  *H5O__mtime_copy(const void *_mesg, void *_dest);
34
static size_t H5O__mtime_size(const H5F_t *f, bool disable_shared, const void *_mesg);
35
static herr_t H5O__mtime_free(void *_mesg);
36
static herr_t H5O__mtime_debug(H5F_t *f, const void *_mesg, FILE *stream, int indent, int fwidth);
37
38
/* This message derives from H5O message class */
39
const H5O_msg_class_t H5O_MSG_MTIME[1] = {{
40
    H5O_MTIME_ID,      /*message id number    */
41
    "mtime",           /*message name for debugging */
42
    sizeof(time_t),    /*native message size    */
43
    0,                 /* messages are shareable?       */
44
    H5O__mtime_decode, /*decode message   */
45
    H5O__mtime_encode, /*encode message   */
46
    H5O__mtime_copy,   /*copy the native value    */
47
    H5O__mtime_size,   /*raw message size   */
48
    NULL,              /* reset method      */
49
    H5O__mtime_free,   /* free method     */
50
    NULL,              /* file delete method    */
51
    NULL,              /* link method     */
52
    NULL,              /*set share method   */
53
    NULL,              /*can share method   */
54
    NULL,              /* pre copy native value to file */
55
    NULL,              /* copy native value to file    */
56
    NULL,              /* post copy native value to file    */
57
    NULL,              /* get creation index    */
58
    NULL,              /* set creation index    */
59
    H5O__mtime_debug   /*debug the message    */
60
}};
61
62
/* This message derives from H5O message class */
63
/* (Only encode, decode & size routines are different from old mtime routines) */
64
const H5O_msg_class_t H5O_MSG_MTIME_NEW[1] = {{
65
    H5O_MTIME_NEW_ID,      /*message id number    */
66
    "mtime_new",           /*message name for debugging */
67
    sizeof(time_t),        /*native message size    */
68
    0,                     /* messages are shareable?       */
69
    H5O__mtime_new_decode, /*decode message   */
70
    H5O__mtime_new_encode, /*encode message   */
71
    H5O__mtime_copy,       /*copy the native value    */
72
    H5O__mtime_new_size,   /*raw message size   */
73
    NULL,                  /* reset method      */
74
    H5O__mtime_free,       /* free method     */
75
    NULL,                  /* file delete method    */
76
    NULL,                  /* link method     */
77
    NULL,                  /*set share method   */
78
    NULL,                  /*can share method   */
79
    NULL,                  /* pre copy native value to file */
80
    NULL,                  /* copy native value to file    */
81
    NULL,                  /* post copy native value to file    */
82
    NULL,                  /* get creation index    */
83
    NULL,                  /* set creation index    */
84
    H5O__mtime_debug       /*debug the message    */
85
}};
86
87
/* Current version of new mtime information */
88
51
#define H5O_MTIME_VERSION 1
89
90
/* Declare a free list to manage the time_t struct */
91
H5FL_DEFINE(time_t);
92
93
/*-------------------------------------------------------------------------
94
 * Function:    H5O__mtime_new_decode
95
 *
96
 * Purpose:     Decode a new modification time message and return a pointer to
97
 *              a new time_t value.
98
 *
99
 *              This version of the modification time was used in HDF5
100
 *              1.6.1 and later.
101
 *
102
 *              The new modification time message format was added due to the
103
 *              performance overhead of the old format.
104
 *
105
 * Return:      Success:    Pointer to new message in native struct
106
 *              Failure:    NULL
107
 *-------------------------------------------------------------------------
108
 */
109
static void *
110
H5O__mtime_new_decode(H5F_t H5_ATTR_NDEBUG_UNUSED *f, H5O_t H5_ATTR_UNUSED *open_oh,
111
                      unsigned H5_ATTR_UNUSED mesg_flags, unsigned H5_ATTR_UNUSED *ioflags, size_t p_size,
112
                      const uint8_t *p)
113
49
{
114
49
    const uint8_t *p_end = p + p_size - 1; /* End of input buffer */
115
49
    time_t        *mesg  = NULL;
116
49
    uint32_t       tmp_time;         /* Temporary copy of the time */
117
49
    void          *ret_value = NULL; /* Return value */
118
119
49
    FUNC_ENTER_PACKAGE
120
121
49
    assert(f);
122
49
    assert(p);
123
124
49
    if (H5_IS_BUFFER_OVERFLOW(p, 1, p_end))
125
0
        HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, NULL, "ran off end of input buffer while decoding");
126
49
    if (*p++ != H5O_MTIME_VERSION)
127
0
        HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "bad version number for mtime message");
128
129
    /* Skip reserved bytes */
130
49
    if (H5_IS_BUFFER_OVERFLOW(p, 3, p_end))
131
0
        HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, NULL, "ran off end of input buffer while decoding");
132
49
    p += 3;
133
134
    /* Get the time_t from the file */
135
49
    if (H5_IS_BUFFER_OVERFLOW(p, 4, p_end))
136
0
        HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, NULL, "ran off end of input buffer while decoding");
137
49
    UINT32DECODE(p, tmp_time);
138
139
    /* The return value */
140
49
    if (NULL == (mesg = H5FL_MALLOC(time_t)))
141
0
        HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed");
142
49
    *mesg = (time_t)tmp_time;
143
144
    /* Set return value */
145
49
    ret_value = mesg;
146
147
49
done:
148
49
    FUNC_LEAVE_NOAPI(ret_value)
149
49
} /* end H5O__mtime_new_decode() */
150
151
/*-------------------------------------------------------------------------
152
 * Function:  H5O__mtime_decode
153
 *
154
 * Purpose:     Decode a modification time message and return a pointer to a
155
 *              new time_t value.
156
 *
157
 *              This version of the modification time was used in HDF5
158
 *              1.6.0 and earlier.
159
 *
160
 *              The new modification time message format was added due to the
161
 *              performance overhead of the old format.
162
 *
163
 * Return:      Success:    Pointer to new message in native struct
164
 *              Failure:    NULL
165
 *-------------------------------------------------------------------------
166
 */
167
static void *
168
H5O__mtime_decode(H5F_t H5_ATTR_NDEBUG_UNUSED *f, H5O_t H5_ATTR_UNUSED *open_oh,
169
                  unsigned H5_ATTR_UNUSED mesg_flags, unsigned H5_ATTR_UNUSED *ioflags, size_t p_size,
170
                  const uint8_t *p)
171
302
{
172
302
    const uint8_t *p_end = p + p_size - 1; /* End of input buffer */
173
302
    time_t        *mesg  = NULL;
174
302
    time_t         the_time;
175
302
    struct tm      tm;
176
302
    void          *ret_value = NULL;
177
178
302
    FUNC_ENTER_PACKAGE
179
180
302
    assert(f);
181
302
    assert(p);
182
183
    /* Buffer should have 14 message bytes and 2 reserved bytes */
184
302
    if (H5_IS_BUFFER_OVERFLOW(p, 16, p_end))
185
0
        HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, NULL, "ran off end of input buffer while decoding");
186
4.47k
    for (int i = 0; i < 14; i++)
187
4.17k
        if (!isdigit(p[i]))
188
5
            HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, NULL, "badly formatted modification time message");
189
190
    /* Convert YYYYMMDDhhmmss UTC to a time_t. */
191
297
    memset(&tm, 0, sizeof tm);
192
297
    tm.tm_year  = (p[0] - '0') * 1000 + (p[1] - '0') * 100 + (p[2] - '0') * 10 + (p[3] - '0') - 1900;
193
297
    tm.tm_mon   = (p[4] - '0') * 10 + (p[5] - '0') - 1;
194
297
    tm.tm_mday  = (p[6] - '0') * 10 + (p[7] - '0');
195
297
    tm.tm_hour  = (p[8] - '0') * 10 + (p[9] - '0');
196
297
    tm.tm_min   = (p[10] - '0') * 10 + (p[11] - '0');
197
297
    tm.tm_sec   = (p[12] - '0') * 10 + (p[13] - '0');
198
297
    tm.tm_isdst = -1; /* (figure it out) */
199
297
    if ((time_t)-1 == (the_time = H5_make_time(&tm)))
200
0
        HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, NULL, "can't construct time info");
201
202
    /* The return value */
203
297
    if (NULL == (mesg = H5FL_MALLOC(time_t)))
204
0
        HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed");
205
297
    *mesg = the_time;
206
207
    /* Set return value */
208
297
    ret_value = mesg;
209
210
302
done:
211
302
    FUNC_LEAVE_NOAPI(ret_value)
212
302
} /* end H5O__mtime_decode() */
213
214
/*-------------------------------------------------------------------------
215
 * Function:  H5O__mtime_new_encode
216
 *
217
 * Purpose: Encodes a new modification time message.
218
 *
219
 * Return:  Non-negative on success/Negative on failure
220
 *
221
 *-------------------------------------------------------------------------
222
 */
223
static herr_t
224
H5O__mtime_new_encode(H5F_t H5_ATTR_UNUSED *f, bool H5_ATTR_UNUSED disable_shared,
225
                      size_t H5_ATTR_UNUSED p_size, uint8_t *p, const void *_mesg)
226
2
{
227
2
    const time_t *mesg = (const time_t *)_mesg;
228
229
2
    FUNC_ENTER_PACKAGE_NOERR
230
231
    /* check args */
232
2
    assert(f);
233
2
    assert(p);
234
2
    assert(mesg);
235
236
    /* Version */
237
2
    *p++ = H5O_MTIME_VERSION;
238
239
    /* Reserved bytes */
240
2
    *p++ = 0;
241
2
    *p++ = 0;
242
2
    *p++ = 0;
243
244
    /* Encode time */
245
2
    UINT32ENCODE(p, *mesg);
246
247
2
    FUNC_LEAVE_NOAPI(SUCCEED)
248
2
} /* end H5O__mtime_new_encode() */
249
250
/*-------------------------------------------------------------------------
251
 * Function:  H5O__mtime_encode
252
 *
253
 * Purpose: Encodes a modification time message.
254
 *
255
 * Return:  Non-negative on success/Negative on failure
256
 *
257
 *-------------------------------------------------------------------------
258
 */
259
static herr_t
260
H5O__mtime_encode(H5F_t H5_ATTR_UNUSED *f, bool H5_ATTR_UNUSED disable_shared, size_t p_size, uint8_t *p,
261
                  const void *_mesg)
262
0
{
263
0
    const time_t *mesg = (const time_t *)_mesg;
264
0
    struct tm    *tm;
265
266
0
    FUNC_ENTER_PACKAGE_NOERR
267
268
    /* check args */
269
0
    assert(f);
270
0
    assert(p);
271
0
    assert(mesg);
272
273
    /* encode */
274
0
    tm = gmtime(mesg);
275
0
    snprintf((char *)p, p_size, "%04d%02d%02d%02d%02d%02d", 1900 + tm->tm_year, 1 + tm->tm_mon, tm->tm_mday,
276
0
             tm->tm_hour, tm->tm_min, tm->tm_sec);
277
278
0
    FUNC_LEAVE_NOAPI(SUCCEED)
279
0
} /* end H5O__mtime_encode() */
280
281
/*-------------------------------------------------------------------------
282
 * Function:  H5O__mtime_copy
283
 *
284
 * Purpose: Copies a message from _MESG to _DEST, allocating _DEST if
285
 *    necessary.
286
 *
287
 * Return:  Success:  Ptr to _DEST
288
 *
289
 *    Failure:  NULL
290
 *
291
 *-------------------------------------------------------------------------
292
 */
293
static void *
294
H5O__mtime_copy(const void *_mesg, void *_dest)
295
0
{
296
0
    const time_t *mesg      = (const time_t *)_mesg;
297
0
    time_t       *dest      = (time_t *)_dest;
298
0
    void         *ret_value = NULL; /* Return value */
299
300
0
    FUNC_ENTER_PACKAGE
301
302
    /* check args */
303
0
    assert(mesg);
304
0
    if (!dest && NULL == (dest = H5FL_MALLOC(time_t)))
305
0
        HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed");
306
307
    /* copy */
308
0
    *dest = *mesg;
309
310
    /* Set return value */
311
0
    ret_value = dest;
312
313
0
done:
314
0
    FUNC_LEAVE_NOAPI(ret_value)
315
0
} /* end H5O__mtime_copy() */
316
317
/*-------------------------------------------------------------------------
318
 * Function:  H5O__mtime_new_size
319
 *
320
 * Purpose: Returns the size of the raw message in bytes not
321
 *    counting the message type or size fields, but only the data
322
 *    fields.  This function doesn't take into account
323
 *    alignment.
324
 *
325
 * Return:  Success:  Message data size in bytes w/o alignment.
326
 *
327
 *    Failure:  0
328
 *
329
 *-------------------------------------------------------------------------
330
 */
331
static size_t
332
H5O__mtime_new_size(const H5F_t H5_ATTR_UNUSED *f, bool H5_ATTR_UNUSED disable_shared,
333
                    const void H5_ATTR_UNUSED *mesg)
334
0
{
335
0
    FUNC_ENTER_PACKAGE_NOERR
336
337
    /* check args */
338
0
    assert(f);
339
0
    assert(mesg);
340
341
0
    FUNC_LEAVE_NOAPI(8)
342
0
} /* end H5O__mtime_new_size() */
343
344
/*-------------------------------------------------------------------------
345
 * Function:  H5O__mtime_size
346
 *
347
 * Purpose: Returns the size of the raw message in bytes not
348
 *    counting the message type or size fields, but only the data
349
 *    fields.  This function doesn't take into account
350
 *    alignment.
351
 *
352
 * Return:  Success:  Message data size in bytes w/o alignment.
353
 *
354
 *    Failure:  0
355
 *
356
 *-------------------------------------------------------------------------
357
 */
358
static size_t
359
H5O__mtime_size(const H5F_t H5_ATTR_UNUSED *f, bool H5_ATTR_UNUSED disable_shared,
360
                const void H5_ATTR_UNUSED *mesg)
361
0
{
362
0
    FUNC_ENTER_PACKAGE_NOERR
363
364
    /* check args */
365
0
    assert(f);
366
0
    assert(mesg);
367
368
0
    FUNC_LEAVE_NOAPI(16)
369
0
} /* end H5O__mtime_size() */
370
371
/*-------------------------------------------------------------------------
372
 * Function:  H5O__mtime_free
373
 *
374
 * Purpose: Frees the message
375
 *
376
 * Return:  Non-negative on success/Negative on failure
377
 *
378
 *-------------------------------------------------------------------------
379
 */
380
static herr_t
381
H5O__mtime_free(void *mesg)
382
346
{
383
346
    FUNC_ENTER_PACKAGE_NOERR
384
385
346
    assert(mesg);
386
387
346
    mesg = H5FL_FREE(time_t, mesg);
388
389
346
    FUNC_LEAVE_NOAPI(SUCCEED)
390
346
} /* end H5O__mtime_free() */
391
392
/*-------------------------------------------------------------------------
393
 * Function:  H5O__mtime_debug
394
 *
395
 * Purpose: Prints debugging info for the message.
396
 *
397
 * Return:  Non-negative on success/Negative on failure
398
 *
399
 *-------------------------------------------------------------------------
400
 */
401
static herr_t
402
H5O__mtime_debug(H5F_t H5_ATTR_UNUSED *f, const void *_mesg, FILE *stream, int indent, int fwidth)
403
0
{
404
0
    const time_t *mesg = (const time_t *)_mesg;
405
0
    struct tm    *tm;
406
0
    char          buf[128];
407
408
0
    FUNC_ENTER_PACKAGE_NOERR
409
410
    /* check args */
411
0
    assert(f);
412
0
    assert(mesg);
413
0
    assert(stream);
414
0
    assert(indent >= 0);
415
0
    assert(fwidth >= 0);
416
417
    /* debug */
418
0
    tm = localtime(mesg);
419
420
0
    strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S %Z", tm);
421
0
    fprintf(stream, "%*s%-*s %s\n", indent, "", fwidth, "Time:", buf);
422
423
0
    FUNC_LEAVE_NOAPI(SUCCEED)
424
0
} /* end H5O__mtime_debug() */