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