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://support.hdfgroup.org/ftp/HDF5/releases.  *
10  * If you do not have access to either file, you may request a copy from     *
11  * help@hdfgroup.org.                                                        *
12  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
13 
14 #define H5A_FRIEND		/*suppress error about including H5Apkg   */
15 #include "H5Omodule.h"          /* This source code file is part of the H5O module */
16 #define H5S_FRIEND	        /*suppress error about including H5Spkg	  */
17 
18 
19 #include "H5private.h"		/* Generic Functions			*/
20 #include "H5Apkg.h"		/* Attributes				*/
21 #include "H5Eprivate.h"		/* Error handling		  	*/
22 #include "H5MMprivate.h"	/* Memory management			*/
23 #include "H5Opkg.h"             /* Object headers			*/
24 #include "H5Spkg.h"		/* Dataspaces				*/
25 
26 /* PRIVATE PROTOTYPES */
27 static herr_t H5O_attr_encode(H5F_t *f, uint8_t *p, const void *mesg);
28 static void *H5O_attr_decode(H5F_t *f, H5O_t *open_oh,
29     unsigned mesg_flags, unsigned *ioflags, size_t p_size, const uint8_t *p);
30 static void *H5O_attr_copy(const void *_mesg, void *_dest);
31 static size_t H5O_attr_size(const H5F_t *f, const void *_mesg);
32 static herr_t H5O__attr_free(void *mesg);
33 static herr_t H5O_attr_pre_copy_file(H5F_t *file_src, const void *mesg_src,
34     hbool_t *deleted, const H5O_copy_t *cpy_info, void *udata);
35 static void *H5O__attr_copy_file(H5F_t *file_src, const H5O_msg_class_t *mesg_type,
36     void *native_src, H5F_t *file_dst, hbool_t *recompute_size,
37     H5O_copy_t *cpy_info, void *udata);
38 static herr_t H5O__attr_post_copy_file(const H5O_loc_t *src_oloc,
39     const void *mesg_src, H5O_loc_t *dst_oloc, void *mesg_dst,
40     H5O_copy_t *cpy_info);
41 static herr_t H5O_attr_get_crt_index(const void *_mesg, H5O_msg_crt_idx_t *crt_idx);
42 static herr_t H5O_attr_set_crt_index(void *_mesg, H5O_msg_crt_idx_t crt_idx);
43 static herr_t H5O__attr_debug(H5F_t *f, const void *_mesg, FILE * stream,
44     int indent, int fwidth);
45 
46 /* Set up & include shared message "interface" info */
47 #define H5O_SHARED_TYPE			H5O_MSG_ATTR
48 #define H5O_SHARED_DECODE		H5O_attr_shared_decode
49 #define H5O_SHARED_DECODE_REAL		H5O_attr_decode
50 #define H5O_SHARED_ENCODE		H5O_attr_shared_encode
51 #define H5O_SHARED_ENCODE_REAL		H5O_attr_encode
52 #define H5O_SHARED_SIZE			H5O_attr_shared_size
53 #define H5O_SHARED_SIZE_REAL		H5O_attr_size
54 #define H5O_SHARED_DELETE		H5O__attr_shared_delete
55 #define H5O_SHARED_DELETE_REAL		H5O__attr_delete
56 #define H5O_SHARED_LINK			H5O__attr_shared_link
57 #define H5O_SHARED_LINK_REAL		H5O__attr_link
58 #define H5O_SHARED_COPY_FILE		H5O__attr_shared_copy_file
59 #define H5O_SHARED_COPY_FILE_REAL	H5O__attr_copy_file
60 #define H5O_SHARED_POST_COPY_FILE	H5O_attr_shared_post_copy_file
61 #define H5O_SHARED_POST_COPY_FILE_REAL	H5O__attr_post_copy_file
62 #undef  H5O_SHARED_POST_COPY_FILE_UPD
63 #define H5O_SHARED_DEBUG		H5O_attr_shared_debug
64 #define H5O_SHARED_DEBUG_REAL		H5O__attr_debug
65 #include "H5Oshared.h"			/* Shared Object Header Message Callbacks */
66 
67 /* This message derives from H5O message class */
68 const H5O_msg_class_t H5O_MSG_ATTR[1] = {{
69     H5O_ATTR_ID,		/* message id number            */
70     "attribute",		/* message name for debugging   */
71     sizeof(H5A_t),		/* native message size          */
72     H5O_SHARE_IS_SHARABLE,	/* messages are sharable?       */
73     H5O_attr_shared_decode,	/* decode message               */
74     H5O_attr_shared_encode,	/* encode message               */
75     H5O_attr_copy,		/* copy the native value        */
76     H5O_attr_shared_size,	/* size of raw message          */
77     H5O__attr_reset,	        /* reset method                 */
78     H5O__attr_free,	        /* free method			*/
79     H5O__attr_shared_delete,	/* file delete method		*/
80     H5O__attr_shared_link,	/* link method			*/
81     NULL,			/*set share method		*/
82     NULL,		    	/*can share method		*/
83     H5O_attr_pre_copy_file,	/* pre copy native value to file */
84     H5O__attr_shared_copy_file,	/* copy native value to file    */
85     H5O_attr_shared_post_copy_file,	/* post copy native value to file    */
86     H5O_attr_get_crt_index,	/* get creation index		*/
87     H5O_attr_set_crt_index,	/* set creation index		*/
88     H5O_attr_shared_debug	/* debug the message            */
89 }};
90 
91 /* Flags for attribute flag encoding */
92 #define H5O_ATTR_FLAG_TYPE_SHARED       0x01
93 #define H5O_ATTR_FLAG_SPACE_SHARED      0x02
94 #define H5O_ATTR_FLAG_ALL               0x03
95 
96 /* Declare external the free list for H5S_t's */
97 H5FL_EXTERN(H5S_t);
98 
99 /* Declare external the free list for H5S_extent_t's */
100 H5FL_EXTERN(H5S_extent_t);
101 
102 
103 /*--------------------------------------------------------------------------
104  NAME
105     H5O_attr_decode
106  PURPOSE
107     Decode a attribute message and return a pointer to a memory struct
108         with the decoded information
109  USAGE
110     void *H5O_attr_decode(f, mesg_flags, p)
111         H5F_t *f;               IN: pointer to the HDF5 file struct
112         unsigned mesg_flags;    IN: Message flags to influence decoding
113         const uint8_t *p;       IN: the raw information buffer
114  RETURNS
115     Pointer to the new message in native order on success, NULL on failure
116  DESCRIPTION
117         This function decodes the "raw" disk form of a attribute message
118     into a struct in memory native format.  The struct is allocated within this
119     function using malloc() and is returned to the caller.
120 --------------------------------------------------------------------------*/
121 static void *
H5O_attr_decode(H5F_t * f,H5O_t * open_oh,unsigned H5_ATTR_UNUSED mesg_flags,unsigned * ioflags,size_t H5_ATTR_UNUSED p_size,const uint8_t * p)122 H5O_attr_decode(H5F_t *f, H5O_t *open_oh, unsigned H5_ATTR_UNUSED mesg_flags,
123     unsigned *ioflags, size_t H5_ATTR_UNUSED p_size, const uint8_t *p)
124 {
125     H5A_t		*attr = NULL;
126     H5S_extent_t	*extent;	/*extent dimensionality information  */
127     size_t		name_len;   	/*attribute name length */
128     size_t		dt_size;   	/* Datatype size */
129     hssize_t		sds_size;   	/* Signed Dataspace size */
130     hsize_t		ds_size;   	/* Dataspace size */
131     unsigned            flags = 0;      /* Attribute flags */
132     H5A_t		*ret_value = NULL;      /* Return value */
133 
134     FUNC_ENTER_NOAPI_NOINIT
135 
136     /* check args */
137     HDassert(f);
138     HDassert(p);
139 
140     if(NULL == (attr = H5FL_CALLOC(H5A_t)))
141 	HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
142 
143     if(NULL == (attr->shared = H5FL_CALLOC(H5A_shared_t)))
144         HGOTO_ERROR(H5E_FILE, H5E_NOSPACE, NULL, "can't allocate shared attr structure")
145 
146     /* Version number */
147     attr->shared->version = *p++;
148     if(attr->shared->version < H5O_ATTR_VERSION_1 || attr->shared->version > H5O_ATTR_VERSION_LATEST)
149 	HGOTO_ERROR(H5E_ATTR, H5E_CANTLOAD, NULL, "bad version number for attribute message")
150 
151     /* Get the flags byte if we have a later version of the attribute */
152     if(attr->shared->version >= H5O_ATTR_VERSION_2) {
153         flags = *p++;
154 
155         /* Check for unknown flag */
156         if(flags & (unsigned)~H5O_ATTR_FLAG_ALL)
157             HGOTO_ERROR(H5E_ATTR, H5E_CANTLOAD, NULL, "unknown flag for attribute message")
158     } /* end if */
159     else
160         p++;    /* Byte is unused when version<2 */
161 
162     /*
163      * Decode the sizes of the parts of the attribute.  The sizes stored in
164      * the file are exact but the parts are aligned on 8-byte boundaries.
165      */
166     UINT16DECODE(p, name_len); /*including null*/
167     UINT16DECODE(p, attr->shared->dt_size);
168     UINT16DECODE(p, attr->shared->ds_size);
169 
170     /*
171      * Decode the character encoding for the name for versions 3 or later,
172      * as well as some reserved bytes.
173      */
174     if(attr->shared->version >= H5O_ATTR_VERSION_3)
175         attr->shared->encoding = (H5T_cset_t)*p++;
176 
177     /* Decode and store the name */
178     if(NULL == (attr->shared->name = H5MM_strdup((const char *)p)))
179 	HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
180     if(attr->shared->version < H5O_ATTR_VERSION_2)
181         p += H5O_ALIGN_OLD(name_len);    /* advance the memory pointer */
182     else
183         p += name_len;    /* advance the memory pointer */
184 
185     /* Decode the attribute's datatype */
186     if(NULL == (attr->shared->dt = (H5T_t *)(H5O_MSG_DTYPE->decode)(f, open_oh,
187         ((flags & H5O_ATTR_FLAG_TYPE_SHARED) ? H5O_MSG_FLAG_SHARED : 0), ioflags, attr->shared->dt_size, p)))
188         HGOTO_ERROR(H5E_ATTR, H5E_CANTDECODE, NULL, "can't decode attribute datatype")
189     if(attr->shared->version < H5O_ATTR_VERSION_2)
190         p += H5O_ALIGN_OLD(attr->shared->dt_size);
191     else
192         p += attr->shared->dt_size;
193 
194     /* decode the attribute dataspace.  It can be shared in versions >= 3
195      * What's actually shared, though, is only the extent.
196      */
197     if(NULL == (attr->shared->ds = H5FL_CALLOC(H5S_t)))
198 	HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
199 
200     /* Decode attribute's dataspace extent */
201     if((extent = (H5S_extent_t *)(H5O_MSG_SDSPACE->decode)(f, open_oh,
202             ((flags & H5O_ATTR_FLAG_SPACE_SHARED) ? H5O_MSG_FLAG_SHARED : 0), ioflags, attr->shared->ds_size, p)) == NULL)
203         HGOTO_ERROR(H5E_ATTR, H5E_CANTDECODE, NULL, "can't decode attribute dataspace")
204 
205     /* Copy the extent information to the dataspace */
206     HDmemcpy(&(attr->shared->ds->extent), extent, sizeof(H5S_extent_t));
207 
208     /* Release temporary extent information */
209     extent = H5FL_FREE(H5S_extent_t, extent);
210 
211     /* Default to entire dataspace being selected */
212     if(H5S_select_all(attr->shared->ds, FALSE) < 0)
213         HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSET, NULL, "unable to set all selection")
214 
215     if(attr->shared->version < H5O_ATTR_VERSION_2)
216         p += H5O_ALIGN_OLD(attr->shared->ds_size);
217     else
218         p += attr->shared->ds_size;
219 
220     /* Get the datatype's size */
221     if(0 == (dt_size = H5T_get_size(attr->shared->dt)))
222         HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, NULL, "unable to get datatype size")
223 
224     /* Get the datatype & dataspace sizes */
225     if(0 == (dt_size = H5T_get_size(attr->shared->dt)))
226         HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, NULL, "unable to get datatype size")
227     if((sds_size = H5S_GET_EXTENT_NPOINTS(attr->shared->ds)) < 0)
228         HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, NULL, "unable to get dataspace size")
229     ds_size = (hsize_t)sds_size;
230 
231     /* Compute the size of the data */
232     H5_CHECKED_ASSIGN(attr->shared->data_size, size_t, ds_size * (hsize_t)dt_size, hsize_t);
233 
234     /* Go get the data */
235     if(attr->shared->data_size) {
236         if(NULL == (attr->shared->data = H5FL_BLK_MALLOC(attr_buf, attr->shared->data_size)))
237             HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
238         HDmemcpy(attr->shared->data, p, attr->shared->data_size);
239     } /* end if */
240 
241     /* Increment the reference count for this object header message in cache(compact
242        storage) or for the object from dense storage. */
243     attr->shared->nrefs++;
244 
245     /* Set return value */
246     ret_value = attr;
247 
248 done:
249     if(NULL == ret_value)
250         if(attr) {
251             if(attr->shared) {
252                 /* Free any dynamically allocated items */
253                 if(H5A__free(attr) < 0)
254                     HDONE_ERROR(H5E_ATTR, H5E_CANTRELEASE, NULL, "can't release attribute info")
255 
256                 /* Destroy shared attribute struct */
257                 attr->shared = H5FL_FREE(H5A_shared_t, attr->shared);
258             } /* end if */
259 
260             attr = H5FL_FREE(H5A_t, attr);
261         } /* end if */
262 
263     FUNC_LEAVE_NOAPI(ret_value)
264 } /* end H5O_attr_decode() */
265 
266 
267 /*--------------------------------------------------------------------------
268  NAME
269     H5O_attr_encode
270  PURPOSE
271     Encode a simple attribute message
272  USAGE
273     herr_t H5O_attr_encode(f, p, mesg)
274         H5F_t *f;         IN: pointer to the HDF5 file struct
275         const uint8 *p;         IN: the raw information buffer
276         const void *mesg;       IN: Pointer to the simple datatype struct
277  RETURNS
278     Non-negative on success/Negative on failure
279  DESCRIPTION
280         This function encodes the native memory form of the attribute
281     message in the "raw" disk form.
282 --------------------------------------------------------------------------*/
283 static herr_t
H5O_attr_encode(H5F_t * f,uint8_t * p,const void * mesg)284 H5O_attr_encode(H5F_t *f, uint8_t *p, const void *mesg)
285 {
286     const H5A_t *attr = (const H5A_t *) mesg;
287     size_t      name_len;   /* Attribute name length */
288     htri_t      is_type_shared;    /* Flag to indicate that a shared datatype is used for this attribute */
289     htri_t      is_space_shared;   /* Flag to indicate that a shared dataspace is used for this attribute */
290     unsigned    flags = 0;      /* Attribute flags */
291     herr_t      ret_value = SUCCEED;      /* Return value */
292 
293     FUNC_ENTER_NOAPI_NOINIT
294 
295     /* check args */
296     HDassert(f);
297     HDassert(p);
298     HDassert(attr);
299 
300     /* Check whether datatype and dataspace are shared */
301     if((is_type_shared = H5O_msg_is_shared(H5O_DTYPE_ID, attr->shared->dt)) < 0)
302         HGOTO_ERROR(H5E_OHDR, H5E_BADMESG, FAIL, "can't determine if datatype is shared")
303 
304     if((is_space_shared = H5O_msg_is_shared(H5O_SDSPACE_ID, attr->shared->ds)) < 0)
305         HGOTO_ERROR(H5E_OHDR, H5E_BADMESG, FAIL, "can't determine if dataspace is shared")
306 
307     /* Encode Version */
308     *p++ = attr->shared->version;
309 
310     /* Set attribute flags if version >1 */
311     if(attr->shared->version >= H5O_ATTR_VERSION_2) {
312         flags = (is_type_shared ? H5O_ATTR_FLAG_TYPE_SHARED : 0 );
313         flags |= (is_space_shared ? H5O_ATTR_FLAG_SPACE_SHARED : 0);
314         *p++ = (uint8_t)flags;    /* Set flags for attribute */
315     } /* end if */
316     else
317         *p++ = 0; /* Reserved, for version <2 */
318 
319     /*
320      * Encode the lengths of the various parts of the attribute message. The
321      * encoded lengths are exact but we pad each part except the data to be a
322      * multiple of eight bytes (in the first version).
323      */
324     name_len = HDstrlen(attr->shared->name) + 1;
325     UINT16ENCODE(p, name_len);
326     UINT16ENCODE(p, attr->shared->dt_size);
327     UINT16ENCODE(p, attr->shared->ds_size);
328 
329     /* The character encoding for the attribute's name, in later versions */
330     if(attr->shared->version >= H5O_ATTR_VERSION_3)
331         *p++ = attr->shared->encoding;
332 
333     /* Write the name including null terminator */
334     HDmemcpy(p, attr->shared->name, name_len);
335     if(attr->shared->version < H5O_ATTR_VERSION_2) {
336         /* Pad to the correct number of bytes */
337         HDmemset(p + name_len, 0, H5O_ALIGN_OLD(name_len) - name_len);
338         p += H5O_ALIGN_OLD(name_len);
339     } /* end if */
340     else
341         p += name_len;
342 
343     /* encode the attribute datatype */
344     if((H5O_MSG_DTYPE->encode)(f, FALSE, p, attr->shared->dt) < 0)
345         HGOTO_ERROR(H5E_ATTR, H5E_CANTENCODE, FAIL, "can't encode attribute datatype")
346 
347     if(attr->shared->version < H5O_ATTR_VERSION_2) {
348         HDmemset(p + attr->shared->dt_size, 0, H5O_ALIGN_OLD(attr->shared->dt_size) - attr->shared->dt_size);
349         p += H5O_ALIGN_OLD(attr->shared->dt_size);
350     } /* end if */
351     else
352         p += attr->shared->dt_size;
353 
354     /* encode the attribute dataspace */
355     if((H5O_MSG_SDSPACE->encode)(f, FALSE, p, &(attr->shared->ds->extent)) < 0)
356         HGOTO_ERROR(H5E_ATTR, H5E_CANTENCODE, FAIL, "can't encode attribute dataspace")
357 
358     if(attr->shared->version < H5O_ATTR_VERSION_2) {
359         HDmemset(p + attr->shared->ds_size, 0, H5O_ALIGN_OLD(attr->shared->ds_size) - attr->shared->ds_size);
360         p += H5O_ALIGN_OLD(attr->shared->ds_size);
361     } /* end if */
362     else
363         p += attr->shared->ds_size;
364 
365     /* Store attribute data.  If there's no data, store 0 as fill value. */
366     if(attr->shared->data)
367         HDmemcpy(p, attr->shared->data, attr->shared->data_size);
368     else
369         HDmemset(p, 0, attr->shared->data_size);
370 
371 done:
372     FUNC_LEAVE_NOAPI(ret_value);
373 } /* end H5O_attr_encode() */
374 
375 
376 /*--------------------------------------------------------------------------
377  NAME
378     H5O_attr_copy
379  PURPOSE
380     Copies a message from MESG to DEST, allocating DEST if necessary.
381  USAGE
382     void *H5O_attr_copy(mesg, dest)
383         const void *mesg;       IN: Pointer to the source attribute struct
384         const void *dest;       IN: Pointer to the destination attribute struct
385  RETURNS
386     Pointer to DEST on success, NULL on failure
387  DESCRIPTION
388         This function copies a native (memory) attribute message,
389     allocating the destination structure if necessary.
390 --------------------------------------------------------------------------*/
391 static void *
H5O_attr_copy(const void * _src,void * _dst)392 H5O_attr_copy(const void *_src, void *_dst)
393 {
394     void *ret_value = NULL;            /* Return value */
395 
396     FUNC_ENTER_NOAPI_NOINIT
397 
398     /* check args */
399     HDassert(_src);
400 
401     /* copy */
402     if(NULL == (ret_value = (H5A_t *)H5A__copy((H5A_t *)_dst, (const H5A_t *)_src)))
403         HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, NULL, "can't copy attribute")
404 
405 done:
406     FUNC_LEAVE_NOAPI(ret_value)
407 } /* end H5O_attr_copy() */
408 
409 
410 /*--------------------------------------------------------------------------
411  NAME
412     H5O_attr_size
413  PURPOSE
414     Return the raw message size in bytes
415  USAGE
416     size_t H5O_attr_size(f, mesg)
417         H5F_t *f;         IN: pointer to the HDF5 file struct
418         const void *mesg;     IN: Pointer to the source attribute struct
419  RETURNS
420     Size of message on success, 0 on failure
421  DESCRIPTION
422         This function returns the size of the raw attribute message on
423     success.  (Not counting the message type or size fields, only the data
424     portion of the message).  It doesn't take into account alignment.
425 --------------------------------------------------------------------------*/
426 static size_t
H5O_attr_size(const H5F_t H5_ATTR_UNUSED * f,const void * _mesg)427 H5O_attr_size(const H5F_t H5_ATTR_UNUSED *f, const void *_mesg)
428 {
429     const H5A_t         *attr = (const H5A_t *)_mesg;
430     size_t		name_len;
431     size_t		ret_value = 0;
432 
433     FUNC_ENTER_NOAPI_NOINIT_NOERR
434 
435     HDassert(attr);
436 
437     /* Common size information */
438     ret_value = 1 +				/*version               */
439                 1 +				/*reserved/flags	*/
440                 2 +				/*name size inc. null	*/
441                 2 +				/*type size		*/
442                 2; 				/*space size		*/
443 
444     /* Length of attribute name */
445     name_len = HDstrlen(attr->shared->name) + 1;
446 
447     /* Version-specific size information */
448     if(attr->shared->version == H5O_ATTR_VERSION_1)
449         ret_value += H5O_ALIGN_OLD(name_len) +	/*attribute name	*/
450                     H5O_ALIGN_OLD(attr->shared->dt_size) +	/*datatype		*/
451                     H5O_ALIGN_OLD(attr->shared->ds_size) +	/*dataspace		*/
452                     attr->shared->data_size;		/*the data itself	*/
453     else if(attr->shared->version == H5O_ATTR_VERSION_2)
454         ret_value += name_len	+		/*attribute name	*/
455                     attr->shared->dt_size +		/*datatype		*/
456                     attr->shared->ds_size +		/*dataspace		*/
457                     attr->shared->data_size;		/*the data itself	*/
458     else if(attr->shared->version == H5O_ATTR_VERSION_3)
459         ret_value += 1 +                        /*character encoding    */
460                     name_len	+		/*attribute name	*/
461                     attr->shared->dt_size +		/*datatype		*/
462                     attr->shared->ds_size +		/*dataspace		*/
463                     attr->shared->data_size;		/*the data itself	*/
464     else
465         HDassert(0 && "Bad attribute version");
466 
467     FUNC_LEAVE_NOAPI(ret_value)
468 } /* end H5O_attr_size() */
469 
470 
471 /*-------------------------------------------------------------------------
472  * Function:    H5O__attr_reset
473  *
474  * Purpose:     Frees resources within a attribute message, but doesn't free
475  *              the message itself.
476  *
477  * Return:      Non-negative on success/Negative on failure
478  *
479  * Programmer:  Robb Matzke
480  *              Tuesday, December  9, 1997
481  *
482  *-------------------------------------------------------------------------
483  */
484 herr_t
H5O__attr_reset(void H5_ATTR_UNUSED * _mesg)485 H5O__attr_reset(void H5_ATTR_UNUSED *_mesg)
486 {
487     FUNC_ENTER_PACKAGE_NOERR
488 
489     FUNC_LEAVE_NOAPI(SUCCEED)
490 } /* end H5O__attr_reset() */
491 
492 
493 /*-------------------------------------------------------------------------
494  * Function:	H5O__attr_free
495  *
496  * Purpose:	Frees the message
497  *
498  * Return:	Non-negative on success/Negative on failure
499  *
500  * Programmer:	Quincey Koziol
501  *              Thursday, November 18, 2004
502  *
503  *-------------------------------------------------------------------------
504  */
505 static herr_t
H5O__attr_free(void * mesg)506 H5O__attr_free(void *mesg)
507 {
508     H5A_t *attr = (H5A_t *)mesg;
509     herr_t ret_value = SUCCEED;   /* Return value */
510 
511     FUNC_ENTER_STATIC
512 
513     HDassert(mesg);
514 
515     if(H5A__close(attr) < 0)
516         HGOTO_ERROR(H5E_ATTR, H5E_CANTCLOSEOBJ, FAIL, "unable to close attribute object")
517 
518 done:
519     FUNC_LEAVE_NOAPI(ret_value)
520 } /* end H5O__attr_free() */
521 
522 
523 /*-------------------------------------------------------------------------
524  * Function:    H5O__attr_delete
525  *
526  * Purpose:     Free file space referenced by message
527  *
528  * Return:      Non-negative on success/Negative on failure
529  *
530  * Programmer:  Quincey Koziol
531  *              Friday, September 26, 2003
532  *
533  *-------------------------------------------------------------------------
534  */
535 herr_t
H5O__attr_delete(H5F_t * f,H5O_t * oh,void * _mesg)536 H5O__attr_delete(H5F_t *f, H5O_t *oh, void *_mesg)
537 {
538     H5A_t *attr = (H5A_t *) _mesg;
539     herr_t ret_value = SUCCEED;   /* Return value */
540 
541     FUNC_ENTER_NOAPI_NOINIT
542 
543     /* check args */
544     HDassert(f);
545     HDassert(attr);
546 
547     /* Decrement reference count on datatype in file */
548     if((H5O_MSG_DTYPE->del)(f, oh, attr->shared->dt) < 0)
549         HGOTO_ERROR(H5E_ATTR, H5E_LINKCOUNT, FAIL, "unable to adjust datatype link count")
550 
551     /* Decrement reference count on dataspace in file */
552     if((H5O_MSG_SDSPACE->del)(f, oh, attr->shared->ds) < 0)
553         HGOTO_ERROR(H5E_ATTR, H5E_LINKCOUNT, FAIL, "unable to adjust dataspace link count")
554 
555 done:
556     FUNC_LEAVE_NOAPI(ret_value)
557 } /* end H5O__attr_delete() */
558 
559 
560 /*-------------------------------------------------------------------------
561  * Function:    H5O__attr_link
562  *
563  * Purpose:     Increment reference count on any objects referenced by
564  *              message
565  *
566  * Return:      Non-negative on success/Negative on failure
567  *
568  * Programmer:  Quincey Koziol
569  *              Friday, September 26, 2003
570  *
571  *-------------------------------------------------------------------------
572  */
573 herr_t
H5O__attr_link(H5F_t * f,H5O_t * oh,void * _mesg)574 H5O__attr_link(H5F_t *f, H5O_t *oh, void *_mesg)
575 {
576     H5A_t *attr = (H5A_t *) _mesg;
577     herr_t ret_value = SUCCEED;   /* Return value */
578 
579     FUNC_ENTER_PACKAGE
580 
581     /* check args */
582     HDassert(f);
583     HDassert(attr);
584 
585     /* Re-share attribute's datatype and dataspace to increment their
586      * reference count if they're shared.
587      * Otherwise they may be deleted when the attribute
588      * message is deleted.
589      */
590     /* Increment reference count on datatype & dataspace in file */
591     if((H5O_MSG_DTYPE->link)(f, oh, attr->shared->dt) < 0)
592         HGOTO_ERROR(H5E_ATTR, H5E_LINKCOUNT, FAIL, "unable to adjust datatype link count")
593     if((H5O_MSG_SDSPACE->link)(f, oh, attr->shared->ds) < 0)
594         HGOTO_ERROR(H5E_ATTR, H5E_LINKCOUNT, FAIL, "unable to adjust dataspace link count")
595 
596 done:
597     FUNC_LEAVE_NOAPI(ret_value)
598 } /* end H5O__attr_link() */
599 
600 
601 /*-------------------------------------------------------------------------
602  * Function:    H5O_attr_pre_copy_file
603  *
604  * Purpose:     Perform any necessary actions before copying message between
605  *              files for attribute messages.
606  *
607  * Return:      Success:        Non-negative
608  *
609  *              Failure:        Negative
610  *
611  * Programmer:  Quincey Koziol
612  *              Monday, June 26, 2006
613  *
614  *-------------------------------------------------------------------------
615  */
616 static herr_t
H5O_attr_pre_copy_file(H5F_t H5_ATTR_UNUSED * file_src,const void * native_src,hbool_t * deleted,const H5O_copy_t * cpy_info,void H5_ATTR_UNUSED * udata)617 H5O_attr_pre_copy_file(H5F_t H5_ATTR_UNUSED *file_src, const void *native_src,
618     hbool_t *deleted, const H5O_copy_t *cpy_info, void H5_ATTR_UNUSED *udata)
619 {
620     const H5A_t *attr_src = (const H5A_t *)native_src;  /* Source attribute */
621     herr_t ret_value = SUCCEED;                         /* Return value */
622 
623     FUNC_ENTER_NOAPI_NOINIT
624 
625     /* check args */
626     HDassert(deleted);
627     HDassert(cpy_info);
628     HDassert(cpy_info->file_dst);
629 
630     /* Check to ensure that the version of the message to be copied does not exceed
631        the message version allowed by the destination file's high bound */
632     if(attr_src->shared->version > H5O_attr_ver_bounds[H5F_HIGH_BOUND(cpy_info->file_dst)])
633         HGOTO_ERROR(H5E_OHDR, H5E_BADRANGE, FAIL, "attribute message version out of bounds")
634 
635     /* If we are not copying attributes into the destination file, indicate
636      *  that this message should be deleted.
637      */
638     if(cpy_info->copy_without_attr)
639         *deleted = TRUE;
640 
641 done:
642     FUNC_LEAVE_NOAPI(ret_value)
643 } /* end H5O_attr_pre_copy_file() */
644 
645 
646 /*-------------------------------------------------------------------------
647  * Function:    H5O__attr_copy_file
648  *
649  * Purpose:     Copies a message from _MESG to _DEST in file
650  *
651  * Return:      Success:        Ptr to _DEST
652  *
653  *              Failure:        NULL
654  *
655  * Programmer:  Quincey Koziol
656  *              November 1, 2005
657  *
658  *-------------------------------------------------------------------------
659  */
660 static void *
H5O__attr_copy_file(H5F_t * file_src,const H5O_msg_class_t H5_ATTR_UNUSED * mesg_type,void * native_src,H5F_t * file_dst,hbool_t * recompute_size,H5O_copy_t * cpy_info,void H5_ATTR_UNUSED * udata)661 H5O__attr_copy_file(H5F_t *file_src, const H5O_msg_class_t H5_ATTR_UNUSED *mesg_type,
662     void *native_src, H5F_t *file_dst, hbool_t *recompute_size,
663     H5O_copy_t *cpy_info, void H5_ATTR_UNUSED *udata)
664 {
665     void *ret_value = NULL;     /* Return value */
666 
667     FUNC_ENTER_STATIC
668 
669     /* check args */
670     HDassert(native_src);
671     HDassert(file_dst);
672     HDassert(cpy_info);
673     HDassert(!cpy_info->copy_without_attr);
674 
675     /* Mark datatype as being on disk now.  This step used to be done in a lower level
676      * by H5O_dtype_decode.  But it has been moved up.  Not an ideal place, but no better
677      * place than here. */
678     if(H5T_set_loc(((H5A_t *)native_src)->shared->dt, file_src, H5T_LOC_DISK) < 0)
679         HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, NULL, "invalid datatype location")
680 
681     if(NULL == (ret_value = H5A__attr_copy_file((H5A_t *)native_src, file_dst, recompute_size, cpy_info)))
682         HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, NULL, "can't copy attribute")
683 
684 done:
685     FUNC_LEAVE_NOAPI(ret_value)
686 } /* H5O__attr_copy_file() */
687 
688 
689 /*-------------------------------------------------------------------------
690  * Function:    H5O__attr_post_copy_file
691  *
692  * Purpose:     Finish copying a message from between files.
693  *              We have to copy the values of a reference attribute in the
694  *              post copy because H5O_post_copy_file() fails at the case that
695  *              an object may have a reference attribute that points to the
696  *              object itself.
697  *
698  * Return:      Non-negative on success/Negative on failure
699  *
700  * Programmer:  Peter Cao
701  *              March 6, 2005
702  *
703  *-------------------------------------------------------------------------
704  */
705 static herr_t
H5O__attr_post_copy_file(const H5O_loc_t * src_oloc,const void * mesg_src,H5O_loc_t * dst_oloc,void * mesg_dst,H5O_copy_t * cpy_info)706 H5O__attr_post_copy_file(const H5O_loc_t *src_oloc, const void *mesg_src,
707     H5O_loc_t *dst_oloc, void *mesg_dst, H5O_copy_t *cpy_info)
708 {
709     herr_t ret_value = SUCCEED;   /* Return value */
710 
711     FUNC_ENTER_STATIC
712 
713     if(H5A__attr_post_copy_file(src_oloc, (const H5A_t *)mesg_src, dst_oloc, (H5A_t *)mesg_dst, cpy_info) < 0)
714         HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, FAIL, "can't copy attribute")
715 
716 done:
717     FUNC_LEAVE_NOAPI(ret_value)
718 } /* H5O__attr_post_copy_file() */
719 
720 
721 /*-------------------------------------------------------------------------
722  * Function:	H5O_attr_get_crt_index
723  *
724  * Purpose:	Get creation index from the message
725  *
726  * Return:      Success:        Non-negative
727  *              Failure:        Negative
728  *
729  * Programmer:	Quincey Koziol
730  *              Thursday, January 18, 2007
731  *
732  *-------------------------------------------------------------------------
733  */
734 static herr_t
H5O_attr_get_crt_index(const void * _mesg,H5O_msg_crt_idx_t * crt_idx)735 H5O_attr_get_crt_index(const void *_mesg, H5O_msg_crt_idx_t *crt_idx /*out*/)
736 {
737     const H5A_t  *attr = (const H5A_t *)_mesg;
738 
739     FUNC_ENTER_NOAPI_NOINIT_NOERR
740 
741     HDassert(attr);
742     HDassert(crt_idx);
743 
744     /* Get the attribute's creation index */
745     *crt_idx = attr->shared->crt_idx;
746 
747     FUNC_LEAVE_NOAPI(SUCCEED)
748 } /* end H5O_attr_get_crt_index() */
749 
750 
751 /*-------------------------------------------------------------------------
752  * Function:	H5O_attr_set_crt_index
753  *
754  * Purpose:	Set creation index from the message
755  *
756  * Return:      Success:        Non-negative
757  *              Failure:        Negative
758  *
759  * Programmer:	Quincey Koziol
760  *              Thursday, January 18, 2007
761  *
762  *-------------------------------------------------------------------------
763  */
764 static herr_t
H5O_attr_set_crt_index(void * _mesg,H5O_msg_crt_idx_t crt_idx)765 H5O_attr_set_crt_index(void *_mesg, H5O_msg_crt_idx_t crt_idx)
766 {
767     H5A_t  *attr = (H5A_t *)_mesg;
768 
769     FUNC_ENTER_NOAPI_NOINIT_NOERR
770 
771     HDassert(attr);
772 
773     /* Set the creation index */
774     attr->shared->crt_idx = crt_idx;
775 
776     FUNC_LEAVE_NOAPI(SUCCEED)
777 } /* end H5O_attr_set_crt_index() */
778 
779 
780 /*--------------------------------------------------------------------------
781  NAME
782     H5O__attr_debug
783  PURPOSE
784     Prints debugging information for an attribute message
785  USAGE
786     void *H5O__attr_debug(f, mesg, stream, indent, fwidth)
787         H5F_t *f;               IN: pointer to the HDF5 file struct
788         const void *mesg;       IN: Pointer to the source attribute struct
789         FILE *stream;           IN: Pointer to the stream for output data
790         int indent;            IN: Amount to indent information by
791         int fwidth;            IN: Field width (?)
792  RETURNS
793     Non-negative on success/Negative on failure
794  DESCRIPTION
795         This function prints debugging output to the stream passed as a
796     parameter.
797 --------------------------------------------------------------------------*/
798 static herr_t
H5O__attr_debug(H5F_t * f,const void * _mesg,FILE * stream,int indent,int fwidth)799 H5O__attr_debug(H5F_t *f, const void *_mesg, FILE * stream, int indent, int fwidth)
800 {
801     const H5A_t *mesg = (const H5A_t *)_mesg;
802     const char		*s;             /* Temporary string pointer */
803     char		buf[128];       /* Temporary string buffer */
804     herr_t ret_value = SUCCEED;         /* Return value */
805 
806     FUNC_ENTER_STATIC
807 
808     /* check args */
809     HDassert(f);
810     HDassert(stream);
811     HDassert(indent >= 0);
812     HDassert(fwidth >= 0);
813 
814     HDfprintf(stream, "%*s%-*s \"%s\"\n", indent, "", fwidth,
815 	    "Name:",
816 	    mesg->shared->name);
817     switch(mesg->shared->encoding) {
818         case H5T_CSET_ASCII:
819             s = "ASCII";
820             break;
821 
822         case H5T_CSET_UTF8:
823             s = "UTF-8";
824             break;
825 
826         case H5T_CSET_RESERVED_2:
827         case H5T_CSET_RESERVED_3:
828         case H5T_CSET_RESERVED_4:
829         case H5T_CSET_RESERVED_5:
830         case H5T_CSET_RESERVED_6:
831         case H5T_CSET_RESERVED_7:
832         case H5T_CSET_RESERVED_8:
833         case H5T_CSET_RESERVED_9:
834         case H5T_CSET_RESERVED_10:
835         case H5T_CSET_RESERVED_11:
836         case H5T_CSET_RESERVED_12:
837         case H5T_CSET_RESERVED_13:
838         case H5T_CSET_RESERVED_14:
839         case H5T_CSET_RESERVED_15:
840             HDsnprintf(buf, sizeof(buf), "H5T_CSET_RESERVED_%d", (int)(mesg->shared->encoding));
841             s = buf;
842             break;
843 
844         case H5T_CSET_ERROR:
845         default:
846             HDsnprintf(buf, sizeof(buf), "Unknown character set: %d", (int)(mesg->shared->encoding));
847             s = buf;
848             break;
849     } /* end switch */
850     HDfprintf(stream, "%*s%-*s %s\n", indent, "", fwidth,
851             "Character Set of Name:",
852             s);
853     HDfprintf(stream, "%*s%-*s %t\n", indent, "", fwidth,
854 	    "Object opened:",
855 	    mesg->obj_opened);
856     HDfprintf(stream, "%*s%-*s %a\n", indent, "", fwidth,
857 	    "Object:",
858 	    mesg->oloc.addr);
859 
860     /* Check for attribute creation order index on the attribute */
861     if(mesg->shared->crt_idx != H5O_MAX_CRT_ORDER_IDX)
862         HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth,
863                 "Creation Index:",
864                 (unsigned)mesg->shared->crt_idx);
865 
866     HDfprintf(stream, "%*sDatatype...\n", indent, "");
867     HDfprintf(stream, "%*s%-*s %lu\n", indent + 3, "", MAX(0,fwidth - 3),
868 	    "Encoded Size:",
869 	    (unsigned long)(mesg->shared->dt_size));
870     if((H5O_MSG_DTYPE->debug)(f, mesg->shared->dt, stream, indent + 3, MAX(0, fwidth - 3)) < 0)
871         HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "unable to display datatype message info")
872 
873     HDfprintf(stream, "%*sDataspace...\n", indent, "");
874     HDfprintf(stream, "%*s%-*s %lu\n", indent + 3, "", MAX(0, fwidth - 3),
875 	    "Encoded Size:",
876 	    (unsigned long)(mesg->shared->ds_size));
877     if(H5S_debug(f, mesg->shared->ds, stream, indent + 3, MAX(0, fwidth - 3)) < 0)
878         HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "unable to display dataspace message info")
879 
880 done:
881     FUNC_LEAVE_NOAPI(ret_value)
882 } /* end H5O__attr_debug() */
883 
884