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() */ |