1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2 * Copyright by The HDF Group. *
3 * Copyright by the Board of Trustees of the University of Illinois. *
4 * All rights reserved. *
5 * *
6 * This file is part of HDF5. The full HDF5 copyright notice, including *
7 * terms governing use, modification, and redistribution, is contained in *
8 * the COPYING file, which can be found at the root of the source code *
9 * distribution tree, or in https://www.hdfgroup.org/licenses. *
10 * If you do not have access to either file, you may request a copy from *
11 * help@hdfgroup.org. *
12 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
13
14 #include "H5Omodule.h" /* This source code file is part of the H5O module */
15 #define H5S_FRIEND /*prevent warning from including H5Spkg.h */
16
17 #include "H5private.h" /* Generic Functions */
18 #include "H5Dprivate.h" /* Datasets */
19 #include "H5Eprivate.h" /* Error handling */
20 #include "H5FLprivate.h" /* Free lists */
21 #include "H5Gprivate.h" /* Groups */
22 #include "H5MMprivate.h" /* Memory management */
23 #include "H5Opkg.h" /* Object headers */
24 #include "H5Spkg.h" /* Dataspaces */
25
26 /* PRIVATE PROTOTYPES */
27 static void * H5O__sdspace_decode(H5F_t *f, H5O_t *open_oh, unsigned mesg_flags, unsigned *ioflags,
28 size_t p_size, const uint8_t *p);
29 static herr_t H5O__sdspace_encode(H5F_t *f, uint8_t *p, const void *_mesg);
30 static void * H5O__sdspace_copy(const void *_mesg, void *_dest);
31 static size_t H5O__sdspace_size(const H5F_t *f, const void *_mesg);
32 static herr_t H5O__sdspace_reset(void *_mesg);
33 static herr_t H5O__sdspace_free(void *_mesg);
34 static herr_t H5O__sdspace_pre_copy_file(H5F_t *file_src, const void *mesg_src, hbool_t *deleted,
35 const H5O_copy_t *cpy_info, void *_udata);
36 static herr_t H5O__sdspace_debug(H5F_t *f, const void *_mesg, FILE *stream, int indent, int fwidth);
37
38 /* Set up & include shared message "interface" info */
39 #define H5O_SHARED_TYPE H5O_MSG_SDSPACE
40 #define H5O_SHARED_DECODE H5O__sdspace_shared_decode
41 #define H5O_SHARED_DECODE_REAL H5O__sdspace_decode
42 #define H5O_SHARED_ENCODE H5O__sdspace_shared_encode
43 #define H5O_SHARED_ENCODE_REAL H5O__sdspace_encode
44 #define H5O_SHARED_SIZE H5O__sdspace_shared_size
45 #define H5O_SHARED_SIZE_REAL H5O__sdspace_size
46 #define H5O_SHARED_DELETE H5O__sdspace_shared_delete
47 #undef H5O_SHARED_DELETE_REAL
48 #define H5O_SHARED_LINK H5O__sdspace_shared_link
49 #undef H5O_SHARED_LINK_REAL
50 #define H5O_SHARED_COPY_FILE H5O__sdspace_shared_copy_file
51 #undef H5O_SHARED_COPY_FILE_REAL
52 #define H5O_SHARED_POST_COPY_FILE H5O__sdspace_shared_post_copy_file
53 #undef H5O_SHARED_POST_COPY_FILE_REAL
54 #undef H5O_SHARED_POST_COPY_FILE_UPD
55 #define H5O_SHARED_DEBUG H5O__sdspace_shared_debug
56 #define H5O_SHARED_DEBUG_REAL H5O__sdspace_debug
57 #include "H5Oshared.h" /* Shared Object Header Message Callbacks */
58
59 /* This message derives from H5O message class */
60 const H5O_msg_class_t H5O_MSG_SDSPACE[1] = {{
61 H5O_SDSPACE_ID, /* message id number */
62 "dataspace", /* message name for debugging */
63 sizeof(H5S_extent_t), /* native message size */
64 H5O_SHARE_IS_SHARABLE | H5O_SHARE_IN_OHDR, /* messages are sharable? */
65 H5O__sdspace_shared_decode, /* decode message */
66 H5O__sdspace_shared_encode, /* encode message */
67 H5O__sdspace_copy, /* copy the native value */
68 H5O__sdspace_shared_size, /* size of symbol table entry */
69 H5O__sdspace_reset, /* default reset method */
70 H5O__sdspace_free, /* free method */
71 H5O__sdspace_shared_delete, /* file delete method */
72 H5O__sdspace_shared_link, /* link method */
73 NULL, /* set share method */
74 NULL, /*can share method */
75 H5O__sdspace_pre_copy_file, /* pre copy native value to file */
76 H5O__sdspace_shared_copy_file, /* copy native value to file */
77 H5O__sdspace_shared_post_copy_file, /* post copy native value to file*/
78 NULL, /* get creation index */
79 NULL, /* set creation index */
80 H5O__sdspace_shared_debug /* debug the message */
81 }};
82
83 /* Declare external the free list for H5S_extent_t's */
84 H5FL_EXTERN(H5S_extent_t);
85
86 /* Declare external the free list for hsize_t arrays */
87 H5FL_ARR_EXTERN(hsize_t);
88
89 /*--------------------------------------------------------------------------
90 NAME
91 H5O__sdspace_decode
92 PURPOSE
93 Decode a simple dimensionality message and return a pointer to a memory
94 struct with the decoded information
95 USAGE
96 void *H5O__sdspace_decode(f, mesg_flags, p)
97 H5F_t *f; IN: pointer to the HDF5 file struct
98 unsigned mesg_flags; IN: Message flags to influence decoding
99 const uint8 *p; IN: the raw information buffer
100 RETURNS
101 Pointer to the new message in native order on success, NULL on failure
102 DESCRIPTION
103 This function decodes the "raw" disk form of a simple dimensionality
104 message into a struct in memory native format. The struct is allocated
105 within this function using malloc() and is returned to the caller.
106 --------------------------------------------------------------------------*/
107 static void *
H5O__sdspace_decode(H5F_t * f,H5O_t H5_ATTR_UNUSED * open_oh,unsigned H5_ATTR_UNUSED mesg_flags,unsigned H5_ATTR_UNUSED * ioflags,size_t p_size,const uint8_t * p)108 H5O__sdspace_decode(H5F_t *f, H5O_t H5_ATTR_UNUSED *open_oh, unsigned H5_ATTR_UNUSED mesg_flags,
109 unsigned H5_ATTR_UNUSED *ioflags, size_t p_size, const uint8_t *p)
110 {
111 H5S_extent_t * sdim = NULL; /* New extent dimensionality structure */
112 unsigned flags, version;
113 unsigned i; /* Local counting variable */
114 const uint8_t *p_end = p + p_size - 1; /* End of the p buffer */
115 void * ret_value = NULL; /* Return value */
116
117 FUNC_ENTER_STATIC
118
119 /* check args */
120 HDassert(f);
121 HDassert(p);
122
123 /* decode */
124 if (NULL == (sdim = H5FL_CALLOC(H5S_extent_t)))
125 HGOTO_ERROR(H5E_DATASPACE, H5E_NOSPACE, NULL, "dataspace structure allocation failed")
126
127 /* Check version */
128 version = *p++;
129 if (version < H5O_SDSPACE_VERSION_1 || version > H5O_SDSPACE_VERSION_2)
130 HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, NULL, "wrong version number in dataspace message")
131 sdim->version = version;
132
133 /* Get rank */
134 sdim->rank = *p++;
135 if (sdim->rank > H5S_MAX_RANK)
136 HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, NULL, "simple dataspace dimensionality is too large")
137
138 /* Get dataspace flags for later */
139 flags = *p++;
140
141 /* Get or determine the type of the extent */
142 if (version >= H5O_SDSPACE_VERSION_2) {
143 sdim->type = (H5S_class_t)*p++;
144 if (sdim->type != H5S_SIMPLE && sdim->rank > 0)
145 HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, NULL, "invalid rank for scalar or NULL dataspace")
146 } /* end if */
147 else {
148 /* Set the dataspace type to be simple or scalar as appropriate */
149 if (sdim->rank > 0)
150 sdim->type = H5S_SIMPLE;
151 else
152 sdim->type = H5S_SCALAR;
153
154 /* Increment past reserved byte */
155 p++;
156 } /* end else */
157 HDassert(sdim->type != H5S_NULL || sdim->version >= H5O_SDSPACE_VERSION_2);
158
159 /* Only Version 1 has these reserved bytes */
160 if (version == H5O_SDSPACE_VERSION_1)
161 p += 4; /*reserved*/
162
163 /* Decode dimension sizes */
164 if (sdim->rank > 0) {
165 /* Ensure that rank doesn't cause reading passed buffer's end,
166 due to possible data corruption */
167 uint8_t sizeof_size = H5F_SIZEOF_SIZE(f);
168 if (p + (sizeof_size * sdim->rank - 1) > p_end) {
169 HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, NULL, "rank might cause reading passed buffer's end")
170 }
171
172 if (NULL == (sdim->size = (hsize_t *)H5FL_ARR_MALLOC(hsize_t, (size_t)sdim->rank)))
173 HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
174
175 for (i = 0; i < sdim->rank; i++)
176 H5F_DECODE_LENGTH(f, p, sdim->size[i]);
177
178 if (flags & H5S_VALID_MAX) {
179 if (NULL == (sdim->max = (hsize_t *)H5FL_ARR_MALLOC(hsize_t, (size_t)sdim->rank)))
180 HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
181
182 /* Ensure that rank doesn't cause reading passed buffer's end */
183 if (p + (sizeof_size * sdim->rank - 1) > p_end)
184 HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, NULL, "rank might cause reading passed buffer's end")
185
186 for (i = 0; i < sdim->rank; i++)
187 H5F_DECODE_LENGTH(f, p, sdim->max[i]);
188 } /* end if */
189 } /* end if */
190
191 /* Compute the number of elements in the extent */
192 if (sdim->type == H5S_NULL)
193 sdim->nelem = 0;
194 else {
195 for (i = 0, sdim->nelem = 1; i < sdim->rank; i++)
196 sdim->nelem *= sdim->size[i];
197 } /* end else */
198
199 /* Set return value */
200 ret_value = (void *)sdim; /*success*/
201
202 done:
203 if (!ret_value && sdim) {
204 H5S__extent_release(sdim);
205 sdim = H5FL_FREE(H5S_extent_t, sdim);
206 } /* end if */
207
208 FUNC_LEAVE_NOAPI(ret_value)
209 } /* end H5O__sdspace_decode() */
210
211 /*--------------------------------------------------------------------------
212 NAME
213 H5O__sdspace_encode
214 PURPOSE
215 Encode a simple dimensionality message
216 USAGE
217 herr_t H5O__sdspace_encode(f, raw_size, p, mesg)
218 H5F_t *f; IN: pointer to the HDF5 file struct
219 size_t raw_size; IN: size of the raw information buffer
220 const uint8 *p; IN: the raw information buffer
221 const void *mesg; IN: Pointer to the extent dimensionality struct
222 RETURNS
223 Non-negative on success/Negative on failure
224 DESCRIPTION
225 This function encodes the native memory form of the simple
226 dimensionality message in the "raw" disk form.
227
228 --------------------------------------------------------------------------*/
229 static herr_t
H5O__sdspace_encode(H5F_t * f,uint8_t * p,const void * _mesg)230 H5O__sdspace_encode(H5F_t *f, uint8_t *p, const void *_mesg)
231 {
232 const H5S_extent_t *sdim = (const H5S_extent_t *)_mesg;
233 unsigned flags = 0;
234 unsigned u; /* Local counting variable */
235
236 FUNC_ENTER_STATIC_NOERR
237
238 /* check args */
239 HDassert(f);
240 HDassert(p);
241 HDassert(sdim);
242
243 /* Version */
244 HDassert(sdim->version > 0);
245 HDassert(sdim->type != H5S_NULL || sdim->version >= H5O_SDSPACE_VERSION_2);
246 *p++ = (uint8_t)sdim->version;
247
248 /* Rank */
249 *p++ = (uint8_t)sdim->rank;
250
251 /* Flags */
252 if (sdim->max)
253 flags |= H5S_VALID_MAX;
254 *p++ = (uint8_t)flags;
255
256 /* Dataspace type */
257 if (sdim->version > H5O_SDSPACE_VERSION_1)
258 *p++ = (uint8_t)sdim->type;
259 else {
260 *p++ = 0; /*reserved*/
261 *p++ = 0; /*reserved*/
262 *p++ = 0; /*reserved*/
263 *p++ = 0; /*reserved*/
264 *p++ = 0; /*reserved*/
265 } /* end else */
266
267 /* Encode dataspace dimensions for simple dataspaces */
268 if (H5S_SIMPLE == sdim->type) {
269 /* Encode current & maximum dimensions */
270 if (sdim->rank > 0) {
271 for (u = 0; u < sdim->rank; u++)
272 H5F_ENCODE_LENGTH(f, p, sdim->size[u]);
273 if (flags & H5S_VALID_MAX)
274 for (u = 0; u < sdim->rank; u++)
275 H5F_ENCODE_LENGTH(f, p, sdim->max[u]);
276 } /* end if */
277 } /* end if */
278
279 FUNC_LEAVE_NOAPI(SUCCEED)
280 } /* end H5O__sdspace_encode() */
281
282 /*--------------------------------------------------------------------------
283 NAME
284 H5O__sdspace_copy
285 PURPOSE
286 Copies a message from MESG to DEST, allocating DEST if necessary.
287 USAGE
288 void *H5O__sdspace_copy(_mesg, _dest)
289 const void *_mesg; IN: Pointer to the source extent dimensionality struct
290 const void *_dest; IN: Pointer to the destination extent dimensionality struct
291 RETURNS
292 Pointer to DEST on success, NULL on failure
293 DESCRIPTION
294 This function copies a native (memory) simple dimensionality message,
295 allocating the destination structure if necessary.
296 --------------------------------------------------------------------------*/
297 static void *
H5O__sdspace_copy(const void * _mesg,void * _dest)298 H5O__sdspace_copy(const void *_mesg, void *_dest)
299 {
300 const H5S_extent_t *mesg = (const H5S_extent_t *)_mesg;
301 H5S_extent_t * dest = (H5S_extent_t *)_dest;
302 void * ret_value = NULL; /* Return value */
303
304 FUNC_ENTER_STATIC
305
306 /* check args */
307 HDassert(mesg);
308 if (!dest && NULL == (dest = H5FL_CALLOC(H5S_extent_t)))
309 HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
310
311 /* Copy extent information */
312 if (H5S__extent_copy_real(dest, mesg, TRUE) < 0)
313 HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, NULL, "can't copy extent")
314
315 /* Set return value */
316 ret_value = dest;
317
318 done:
319 if (NULL == ret_value)
320 if (dest && NULL == _dest)
321 dest = H5FL_FREE(H5S_extent_t, dest);
322
323 FUNC_LEAVE_NOAPI(ret_value)
324 } /* end H5O__sdspace_copy() */
325
326 /*--------------------------------------------------------------------------
327 NAME
328 H5O__sdspace_size
329 PURPOSE
330 Return the raw message size in bytes
331 USAGE
332 void *H5O__sdspace_size(f, mesg)
333 H5F_t *f; IN: pointer to the HDF5 file struct
334 const void *mesg; IN: Pointer to the source extent dimensionality struct
335 RETURNS
336 Size of message on success, zero on failure
337 DESCRIPTION
338 This function returns the size of the raw simple dimensionality message on
339 success. (Not counting the message type or size fields, only the data
340 portion of the message). It doesn't take into account alignment.
341
342 --------------------------------------------------------------------------*/
343 static size_t
H5O__sdspace_size(const H5F_t * f,const void * _mesg)344 H5O__sdspace_size(const H5F_t *f, const void *_mesg)
345 {
346 const H5S_extent_t *space = (const H5S_extent_t *)_mesg;
347 size_t ret_value = 0; /* Return value */
348
349 FUNC_ENTER_STATIC_NOERR
350
351 /* Basic information for all dataspace messages */
352 ret_value = (size_t)(1 + /* Version */
353 1 + /* Rank */
354 1 + /* Flags */
355 1 + /* Dataspace type/reserved */
356 ((space->version > H5O_SDSPACE_VERSION_1) ? 0 : 4)); /* Eliminated/reserved */
357
358 /* Add in the dimension sizes */
359 ret_value += space->rank * H5F_SIZEOF_SIZE(f);
360
361 /* Add in the space for the maximum dimensions, if they are present */
362 ret_value += space->max ? (space->rank * H5F_SIZEOF_SIZE(f)) : 0;
363
364 FUNC_LEAVE_NOAPI(ret_value)
365 } /* end H5O__sdspace_size() */
366
367 /*-------------------------------------------------------------------------
368 * Function: H5O__sdspace_reset
369 *
370 * Purpose: Frees the inside of a dataspace message and resets it to some
371 * initial value.
372 *
373 * Return: Non-negative on success/Negative on failure
374 *
375 * Programmer: Robb Matzke
376 * Thursday, April 30, 1998
377 *
378 *-------------------------------------------------------------------------
379 */
380 static herr_t
H5O__sdspace_reset(void * _mesg)381 H5O__sdspace_reset(void *_mesg)
382 {
383 H5S_extent_t *mesg = (H5S_extent_t *)_mesg;
384
385 FUNC_ENTER_STATIC_NOERR
386
387 H5S__extent_release(mesg);
388
389 FUNC_LEAVE_NOAPI(SUCCEED)
390 } /* end H5O__sdspace_reset() */
391
392 /*-------------------------------------------------------------------------
393 * Function: H5O__sdsdpace_free
394 *
395 * Purpose: Frees the message
396 *
397 * Return: Non-negative on success/Negative on failure
398 *
399 * Programmer: Quincey Koziol
400 * Thursday, March 30, 2000
401 *
402 *-------------------------------------------------------------------------
403 */
404 static herr_t
H5O__sdspace_free(void * mesg)405 H5O__sdspace_free(void *mesg)
406 {
407 FUNC_ENTER_STATIC_NOERR
408
409 HDassert(mesg);
410
411 mesg = H5FL_FREE(H5S_extent_t, mesg);
412
413 FUNC_LEAVE_NOAPI(SUCCEED)
414 } /* end H5O__sdspace_free() */
415
416 /*-------------------------------------------------------------------------
417 * Function: H5O__sdspace_pre_copy_file
418 *
419 * Purpose: Perform any necessary actions before copying message between
420 * files
421 *
422 * Return: Success: Non-negative
423 *
424 * Failure: Negative
425 *
426 * Programmer: Quincey Koziol
427 * November 30, 2006
428 *
429 *-------------------------------------------------------------------------
430 */
431 static herr_t
H5O__sdspace_pre_copy_file(H5F_t H5_ATTR_UNUSED * file_src,const void * mesg_src,hbool_t H5_ATTR_UNUSED * deleted,const H5O_copy_t * cpy_info,void * _udata)432 H5O__sdspace_pre_copy_file(H5F_t H5_ATTR_UNUSED *file_src, const void *mesg_src,
433 hbool_t H5_ATTR_UNUSED *deleted, const H5O_copy_t *cpy_info, void *_udata)
434 {
435 const H5S_extent_t *src_space_extent = (const H5S_extent_t *)mesg_src; /* Source dataspace extent */
436 H5D_copy_file_ud_t *udata = (H5D_copy_file_ud_t *)_udata; /* Dataset copying user data */
437 herr_t ret_value = SUCCEED; /* Return value */
438
439 FUNC_ENTER_STATIC
440
441 /* check args */
442 HDassert(file_src);
443 HDassert(src_space_extent);
444 HDassert(cpy_info);
445 HDassert(cpy_info->file_dst);
446
447 /* Check to ensure that the version of the message to be copied does not exceed
448 the message version allowed by the destination file's high bound */
449 if (src_space_extent->version > H5O_sdspace_ver_bounds[H5F_HIGH_BOUND(cpy_info->file_dst)])
450 HGOTO_ERROR(H5E_OHDR, H5E_BADRANGE, FAIL, "dataspace message version out of bounds")
451
452 /* If the user data is non-NULL, assume we are copying a dataset
453 * and make a copy of the dataspace extent for later in the object copying
454 * process. (We currently only need to make a copy of the dataspace extent
455 * if the layout is an early version, but that information isn't
456 * available here, so we just make a copy of it in all cases)
457 */
458 if (udata) {
459 /* Allocate copy of dataspace extent */
460 if (NULL == (udata->src_space_extent = H5FL_CALLOC(H5S_extent_t)))
461 HGOTO_ERROR(H5E_DATASPACE, H5E_NOSPACE, FAIL, "dataspace extent allocation failed")
462
463 /* Create a copy of the dataspace extent */
464 if (H5S__extent_copy_real(udata->src_space_extent, src_space_extent, TRUE) < 0)
465 HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "can't copy extent")
466 } /* end if */
467
468 done:
469 FUNC_LEAVE_NOAPI(ret_value)
470 } /* end H5O_dspace_pre_copy_file() */
471
472 /*--------------------------------------------------------------------------
473 NAME
474 H5O__sdspace_debug
475 PURPOSE
476 Prints debugging information for a simple dimensionality message
477 USAGE
478 void *H5O__sdspace_debug(f, mesg, stream, indent, fwidth)
479 H5F_t *f; IN: pointer to the HDF5 file struct
480 const void *mesg; IN: Pointer to the source extent dimensionality struct
481 FILE *stream; IN: Pointer to the stream for output data
482 int indent; IN: Amount to indent information by
483 int fwidth; IN: Field width (?)
484 RETURNS
485 Non-negative on success/Negative on failure
486 DESCRIPTION
487 This function prints debugging output to the stream passed as a
488 parameter.
489 --------------------------------------------------------------------------*/
490 static herr_t
H5O__sdspace_debug(H5F_t H5_ATTR_UNUSED * f,const void * mesg,FILE * stream,int indent,int fwidth)491 H5O__sdspace_debug(H5F_t H5_ATTR_UNUSED *f, const void *mesg, FILE *stream, int indent, int fwidth)
492 {
493 const H5S_extent_t *sdim = (const H5S_extent_t *)mesg;
494
495 FUNC_ENTER_STATIC_NOERR
496
497 /* check args */
498 HDassert(f);
499 HDassert(sdim);
500 HDassert(stream);
501 HDassert(indent >= 0);
502 HDassert(fwidth >= 0);
503
504 HDfprintf(stream, "%*s%-*s %lu\n", indent, "", fwidth, "Rank:", (unsigned long)(sdim->rank));
505
506 if (sdim->rank > 0) {
507 unsigned u; /* local counting variable */
508
509 HDfprintf(stream, "%*s%-*s {", indent, "", fwidth, "Dim Size:");
510 for (u = 0; u < sdim->rank; u++)
511 HDfprintf(stream, "%s%" PRIuHSIZE, u ? ", " : "", sdim->size[u]);
512 HDfprintf(stream, "}\n");
513
514 HDfprintf(stream, "%*s%-*s ", indent, "", fwidth, "Dim Max:");
515 if (sdim->max) {
516 HDfprintf(stream, "{");
517 for (u = 0; u < sdim->rank; u++) {
518 if (H5S_UNLIMITED == sdim->max[u])
519 HDfprintf(stream, "%sUNLIM", u ? ", " : "");
520 else
521 HDfprintf(stream, "%s%" PRIuHSIZE, u ? ", " : "", sdim->max[u]);
522 } /* end for */
523 HDfprintf(stream, "}\n");
524 } /* end if */
525 else
526 HDfprintf(stream, "CONSTANT\n");
527 } /* end if */
528
529 FUNC_LEAVE_NOAPI(SUCCEED)
530 } /* end H5O__sdspace_debug() */
531