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 /*
15  * Programmer:	Robb Matzke <matzke@llnl.gov>
16  *		Wednesday, April 15, 1998
17  *
18  * Purpose:	Data filter pipeline message.
19  */
20 
21 #include "H5Omodule.h"          /* This source code file is part of the H5O module */
22 #define H5Z_FRIEND		/*suppress error about including H5Zpkg	  */
23 
24 
25 #include "H5private.h"		/* Generic Functions			*/
26 #include "H5Dprivate.h"		/* Datasets				*/
27 #include "H5Eprivate.h"		/* Error handling		  	*/
28 #include "H5FLprivate.h"	/* Free Lists				*/
29 #include "H5MMprivate.h"	/* Memory management			*/
30 #include "H5Opkg.h"             /* Object headers			*/
31 #include "H5Zpkg.h"		/* Data filters				*/
32 
33 
34 /* PRIVATE PROTOTYPES */
35 static herr_t H5O_pline_encode(H5F_t *f, uint8_t *p, const void *mesg);
36 static void *H5O__pline_decode(H5F_t *f, H5O_t *open_oh, unsigned mesg_flags,
37     unsigned *ioflags, size_t p_size, const uint8_t *p);
38 static void *H5O_pline_copy(const void *_mesg, void *_dest);
39 static size_t H5O_pline_size(const H5F_t *f, const void *_mesg);
40 static herr_t H5O__pline_reset(void *_mesg);
41 static herr_t H5O__pline_free(void *_mesg);
42 static herr_t H5O_pline_pre_copy_file(H5F_t *file_src,
43     const void *mesg_src, hbool_t *deleted, const H5O_copy_t *cpy_info, void *_udata);
44 static herr_t H5O__pline_debug(H5F_t *f, const void *_mesg, FILE * stream,
45     int indent, int fwidth);
46 
47 /* Set up & include shared message "interface" info */
48 #define H5O_SHARED_TYPE			H5O_MSG_PLINE
49 #define H5O_SHARED_DECODE		H5O_pline_shared_decode
50 #define H5O_SHARED_DECODE_REAL		H5O__pline_decode
51 #define H5O_SHARED_ENCODE		H5O_pline_shared_encode
52 #define H5O_SHARED_ENCODE_REAL		H5O_pline_encode
53 #define H5O_SHARED_SIZE			H5O_pline_shared_size
54 #define H5O_SHARED_SIZE_REAL		H5O_pline_size
55 #define H5O_SHARED_DELETE		H5O__pline_shared_delete
56 #undef H5O_SHARED_DELETE_REAL
57 #define H5O_SHARED_LINK			H5O__pline_shared_link
58 #undef H5O_SHARED_LINK_REAL
59 #define H5O_SHARED_COPY_FILE		H5O__pline_shared_copy_file
60 #undef H5O_SHARED_COPY_FILE_REAL
61 #define H5O_SHARED_POST_COPY_FILE	H5O_pline_shared_post_copy_file
62 #undef H5O_SHARED_POST_COPY_FILE_REAL
63 #undef  H5O_SHARED_POST_COPY_FILE_UPD
64 #define H5O_SHARED_DEBUG		H5O_pline_shared_debug
65 #define H5O_SHARED_DEBUG_REAL		H5O__pline_debug
66 #include "H5Oshared.h"			/* Shared Object Header Message Callbacks */
67 
68 /* This message derives from H5O message class */
69 const H5O_msg_class_t H5O_MSG_PLINE[1] = {{
70     H5O_PLINE_ID,		/* message id number		*/
71     "filter pipeline",		/* message name for debugging	*/
72     sizeof(H5O_pline_t),	/* native message size		*/
73     H5O_SHARE_IS_SHARABLE|H5O_SHARE_IN_OHDR,	/* messages are sharable?       */
74     H5O_pline_shared_decode,	/* decode message		*/
75     H5O_pline_shared_encode,	/* encode message		*/
76     H5O_pline_copy,		/* copy the native value	*/
77     H5O_pline_shared_size,	/* size of raw message		*/
78     H5O__pline_reset,		/* reset method			*/
79     H5O__pline_free,		/* free method			*/
80     H5O__pline_shared_delete,   /* file delete method		*/
81     H5O__pline_shared_link,	/* link method			*/
82     NULL,			/* set share method		*/
83     NULL,		    	/*can share method		*/
84     H5O_pline_pre_copy_file,	/* pre copy native value to file */
85     H5O__pline_shared_copy_file,	/* copy native value to file    */
86     H5O_pline_shared_post_copy_file,	/* post copy native value to file    */
87     NULL,			/* get creation index		*/
88     NULL,			/* set creation index		*/
89     H5O_pline_shared_debug	/* debug the message		*/
90 }};
91 
92 /* Format version bounds for filter pipleline */
93 const unsigned H5O_pline_ver_bounds[] = {
94     H5O_PLINE_VERSION_1,        /* H5F_LIBVER_EARLIEST */
95     H5O_PLINE_VERSION_2,        /* H5F_LIBVER_V18 */
96     H5O_PLINE_VERSION_LATEST    /* H5F_LIBVER_LATEST */
97 };
98 
99 /* Declare a free list to manage the H5O_pline_t struct */
100 H5FL_DEFINE(H5O_pline_t);
101 
102 
103 /*-------------------------------------------------------------------------
104  * Function:	H5O__pline_decode
105  *
106  * Purpose:	Decodes a filter pipeline message.
107  *
108  * Return:	Success:	Ptr to the native message.
109  *		Failure:	NULL
110  *
111  * Programmer:	Robb Matzke
112  *              Wednesday, April 15, 1998
113  *
114  *-------------------------------------------------------------------------
115  */
116 static void *
H5O__pline_decode(H5F_t H5_ATTR_UNUSED * 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)117 H5O__pline_decode(H5F_t H5_ATTR_UNUSED *f, H5O_t H5_ATTR_UNUSED *open_oh,
118     unsigned H5_ATTR_UNUSED mesg_flags, unsigned H5_ATTR_UNUSED *ioflags,
119     size_t p_size, const uint8_t *p)
120 {
121     H5O_pline_t		*pline = NULL;          /* Pipeline message */
122     H5Z_filter_info_t   *filter;                /* Filter to decode */
123     size_t		name_length;            /* Length of filter name */
124     size_t		i;                      /* Local index variable */
125     const uint8_t *p_end = p + p_size - 1;  /* End of the p buffer */
126     void		*ret_value = NULL;      /* Return value */
127 
128     FUNC_ENTER_STATIC
129 
130     /* check args */
131     HDassert(p);
132 
133     /* Allocate space for I/O pipeline message */
134     if(NULL == (pline = H5FL_CALLOC(H5O_pline_t)))
135         HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
136 
137     /* Version */
138     pline->version = *p++;
139     if(pline->version < H5O_PLINE_VERSION_1 || pline->version > H5O_PLINE_VERSION_LATEST)
140         HGOTO_ERROR(H5E_PLINE, H5E_CANTLOAD, NULL, "bad version number for filter pipeline message")
141 
142     /* Number of filters */
143     pline->nused = *p++;
144     if(pline->nused > H5Z_MAX_NFILTERS) {
145 
146         /* Reset the number of filters used to avoid array traversal in error
147          * handling code.
148          */
149         pline->nused = 0;
150 
151         HGOTO_ERROR(H5E_PLINE, H5E_CANTLOAD, NULL, "filter pipeline message has too many filters")
152     }
153 
154     /* Reserved */
155     if(pline->version == H5O_PLINE_VERSION_1)
156         p += 6;
157 
158     /* Allocate array for filters */
159     pline->nalloc = pline->nused;
160     if(NULL == (pline->filter = (H5Z_filter_info_t *)H5MM_calloc(pline->nalloc * sizeof(pline->filter[0]))))
161         HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
162 
163     /* Decode filters */
164     for(i = 0, filter = &pline->filter[0]; i < pline->nused; i++, filter++) {
165         /* Filter ID */
166         UINT16DECODE(p, filter->id);
167 
168         /* Length of filter name */
169         if(pline->version > H5O_PLINE_VERSION_1 && filter->id < H5Z_FILTER_RESERVED)
170             name_length = 0;
171         else {
172             UINT16DECODE(p, name_length);
173             if(pline->version == H5O_PLINE_VERSION_1 && name_length % 8)
174                 HGOTO_ERROR(H5E_PLINE, H5E_CANTLOAD, NULL, "filter name length is not a multiple of eight")
175         } /* end if */
176 
177         /* Filter flags */
178         UINT16DECODE(p, filter->flags);
179 
180         /* Number of filter parameters ("client data elements") */
181         UINT16DECODE(p, filter->cd_nelmts);
182 
183         /* Filter name, if there is one */
184         if(name_length) {
185             size_t actual_name_length;          /* Actual length of name */
186 
187             /* Determine actual name length (without padding, but with null terminator) */
188             actual_name_length = HDstrlen((const char *)p) + 1;
189             HDassert(actual_name_length <= name_length);
190 
191             /* Allocate space for the filter name, or use the internal buffer */
192             if(actual_name_length > H5Z_COMMON_NAME_LEN) {
193                 filter->name = (char *)H5MM_malloc(actual_name_length);
194                 if(NULL == filter->name)
195                     HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for filter name")
196             } /* end if */
197             else
198                 filter->name = filter->_name;
199 
200             HDstrncpy(filter->name, (const char *)p, actual_name_length);
201             p += name_length;
202         } /* end if */
203 
204         /* Filter parameters */
205         if(filter->cd_nelmts) {
206             size_t	j;              /* Local index variable */
207 
208             /* Allocate space for the client data elements, or use the internal buffer */
209             if(filter->cd_nelmts > H5Z_COMMON_CD_VALUES) {
210                 filter->cd_values = (unsigned *)H5MM_malloc(filter->cd_nelmts * sizeof(unsigned));
211                 if(NULL == filter->cd_values)
212                     HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for client data")
213             } /* end if */
214             else
215                 filter->cd_values = filter->_cd_values;
216 
217             /*
218              * Read the client data values and the padding
219              */
220             for (j = 0; j < filter->cd_nelmts; j++) {
221                 if (p + 4 - 1 <= p_end)
222                     UINT32DECODE(p, filter->cd_values[j])
223                 else
224                     HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "ran off the end of the buffer: current p = %p, p_size = %zu, p_end = %p", p, p_size, p_end)
225             }
226 
227             if(pline->version == H5O_PLINE_VERSION_1)
228                 if(filter->cd_nelmts % 2)
229                     p += 4; /*padding*/
230         } /* end if */
231     } /* end for */
232 
233     /* Set return value */
234     ret_value = pline;
235 
236 done:
237     if(NULL == ret_value && pline) {
238         H5O__pline_reset(pline);
239         H5O__pline_free(pline);
240     } /* end if */
241 
242     FUNC_LEAVE_NOAPI(ret_value)
243 } /* end H5O__pline_decode() */
244 
245 
246 /*-------------------------------------------------------------------------
247  * Function:	H5O_pline_encode
248  *
249  * Purpose:	Encodes message MESG into buffer P.
250  *
251  * Return:	Non-negative on success/Negative on failure
252  *
253  * Programmer:	Robb Matzke
254  *              Wednesday, April 15, 1998
255  *
256  *-------------------------------------------------------------------------
257  */
258 static herr_t
H5O_pline_encode(H5F_t H5_ATTR_UNUSED * f,uint8_t * p,const void * mesg)259 H5O_pline_encode(H5F_t H5_ATTR_UNUSED *f, uint8_t *p/*out*/, const void *mesg)
260 {
261     const H5O_pline_t	*pline = (const H5O_pline_t*)mesg;      /* Pipeline message to encode */
262     const       H5Z_filter_info_t *filter;      /* Filter to encode */
263     size_t	i, j;                   /* Local index variables */
264 
265     FUNC_ENTER_NOAPI_NOINIT_NOERR
266 
267     /* Check args */
268     HDassert(p);
269     HDassert(mesg);
270 
271     /* Message header */
272     *p++ = (uint8_t)pline->version;
273     *p++ = (uint8_t)(pline->nused);
274     if(pline->version == H5O_PLINE_VERSION_1) {
275         *p++ = 0;	/*reserved 1*/
276         *p++ = 0;	/*reserved 2*/
277         *p++ = 0;	/*reserved 3*/
278         *p++ = 0;	/*reserved 4*/
279         *p++ = 0;	/*reserved 5*/
280         *p++ = 0;	/*reserved 6*/
281     } /* end if */
282 
283     /* Encode filters */
284     for(i = 0, filter = &pline->filter[0]; i < pline->nused; i++, filter++) {
285         const char	*name;                  /* Filter name */
286         size_t		name_length;            /* Length of filter name */
287 
288         /* Filter ID */
289 	UINT16ENCODE(p, filter->id);
290 
291         /* Skip writing the name length & name if the filter is an internal filter */
292         if(pline->version > H5O_PLINE_VERSION_1 && filter->id < H5Z_FILTER_RESERVED) {
293             name_length = 0;
294             name = NULL;
295         } /* end if */
296         else {
297             H5Z_class2_t	*cls;                   /* Filter class */
298 
299             /*
300              * Get the filter name.  If the pipeline message has a name in it then
301              * use that one.  Otherwise try to look up the filter and get the name
302              * as it was registered.
303              */
304             if(NULL == (name = filter->name) && (cls = H5Z_find(filter->id)))
305                 name = cls->name;
306             name_length = name ? HDstrlen(name) + 1 : 0;
307 
308             /* Filter name length */
309             UINT16ENCODE(p, pline->version == H5O_PLINE_VERSION_1 ? H5O_ALIGN_OLD(name_length) : name_length);
310         } /* end else */
311 
312         /* Filter flags */
313 	UINT16ENCODE(p, filter->flags);
314 
315         /* # of filter parameters */
316 	UINT16ENCODE(p, filter->cd_nelmts);
317 
318         /* Encode name, if there is one to encode */
319 	if(name_length > 0) {
320             /* Store name, with null terminator */
321 	    HDmemcpy(p, name, name_length);
322 	    p += name_length;
323 
324             /* Pad out name to alignment, in older versions */
325             if(pline->version == H5O_PLINE_VERSION_1)
326                 while(name_length++ % 8)
327                     *p++ = 0;
328 	} /* end if */
329 
330         /* Filter parameters */
331 	for(j = 0; j < filter->cd_nelmts; j++)
332 	    UINT32ENCODE(p, filter->cd_values[j]);
333 
334         /* Align the parameters for older versions of the format */
335         if(pline->version == H5O_PLINE_VERSION_1)
336             if(filter->cd_nelmts % 2)
337                 UINT32ENCODE(p, 0);
338     } /* end for */
339 
340     FUNC_LEAVE_NOAPI(SUCCEED)
341 } /* end H5O_pline_encode() */
342 
343 
344 /*-------------------------------------------------------------------------
345  * Function:	H5O_pline_copy
346  *
347  * Purpose:	Copies a filter pipeline message from SRC to DST allocating
348  *		DST if necessary.  If DST is already allocated then we assume
349  *		that it isn't initialized.
350  *
351  * Return:	Success:	Ptr to DST or allocated result.
352  *
353  *		Failure:	NULL
354  *
355  * Programmer:	Robb Matzke
356  *              Wednesday, April 15, 1998
357  *
358  *-------------------------------------------------------------------------
359  */
360 static void *
H5O_pline_copy(const void * _src,void * _dst)361 H5O_pline_copy(const void *_src, void *_dst/*out*/)
362 {
363     const H5O_pline_t	*src = (const H5O_pline_t *)_src;       /* Source pipeline message */
364     H5O_pline_t		*dst = (H5O_pline_t *)_dst;             /* Destination pipeline message */
365     size_t		i;                      /* Local index variable */
366     H5O_pline_t		*ret_value = NULL;      /* Return value */
367 
368     FUNC_ENTER_NOAPI_NOINIT
369 
370     /* Allocate pipeline message, if not provided */
371     if(!dst && NULL == (dst = H5FL_MALLOC(H5O_pline_t)))
372 	HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
373 
374     /* Shallow copy basic fields */
375     *dst = *src;
376 
377     /* Copy over filters, if any */
378     dst->nalloc = dst->nused;
379     if(dst->nalloc) {
380         /* Allocate array to hold filters */
381 	if(NULL == (dst->filter = (H5Z_filter_info_t *)H5MM_calloc(dst->nalloc * sizeof(dst->filter[0]))))
382 	    HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
383 
384         /* Deep-copy filters */
385         for(i = 0; i < src->nused; i++) {
386             /* Basic filter information */
387             dst->filter[i] = src->filter[i];
388 
389             /* Filter name */
390             if(src->filter[i].name) {
391                 size_t namelen;         /* Length of source filter name, including null terminator  */
392 
393                 namelen = HDstrlen(src->filter[i].name) + 1;
394 
395                 /* Allocate space for the filter name, or use the internal buffer */
396                 if(namelen > H5Z_COMMON_NAME_LEN) {
397                     dst->filter[i].name = (char *)H5MM_strdup(src->filter[i].name);
398                     if(NULL == dst->filter[i].name)
399                         HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for filter name")
400                 } /* end if */
401                 else
402                     dst->filter[i].name = dst->filter[i]._name;
403             } /* end if */
404 
405             /* Filter parameters */
406             if(src->filter[i].cd_nelmts > 0) {
407                 /* Allocate space for the client data elements, or use the internal buffer */
408                 if(src->filter[i].cd_nelmts > H5Z_COMMON_CD_VALUES) {
409                     if(NULL == (dst->filter[i].cd_values = (unsigned *)H5MM_malloc(src->filter[i].cd_nelmts* sizeof(unsigned))))
410                         HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
411 
412                     HDmemcpy(dst->filter[i].cd_values, src->filter[i].cd_values,
413                             src->filter[i].cd_nelmts * sizeof(unsigned));
414                 } /* end if */
415                 else
416                     dst->filter[i].cd_values = dst->filter[i]._cd_values;
417             } /* end if */
418         } /* end for */
419     } /* end if */
420     else
421 	dst->filter = NULL;
422 
423     /* Set return value */
424     ret_value = dst;
425 
426 done:
427     if(!ret_value && dst) {
428         H5O__pline_reset(dst);
429 	if(!_dst)
430             H5O__pline_free(dst);
431     } /* end if */
432 
433     FUNC_LEAVE_NOAPI(ret_value)
434 } /* end H5O_pline_copy() */
435 
436 
437 /*-------------------------------------------------------------------------
438  * Function:	H5O_pline_size
439  *
440  * Purpose:	Determines the size of a raw filter pipeline message.
441  *
442  * Return:	Success:	Size of message.
443  *
444  *		Failure:	zero
445  *
446  * Programmer:	Robb Matzke
447  *              Wednesday, April 15, 1998
448  *
449  *-------------------------------------------------------------------------
450  */
451 static size_t
H5O_pline_size(const H5F_t H5_ATTR_UNUSED * f,const void * mesg)452 H5O_pline_size(const H5F_t H5_ATTR_UNUSED *f, const void *mesg)
453 {
454     const H5O_pline_t	*pline = (const H5O_pline_t*)mesg;      /* Pipeline message */
455     size_t i;                   /* Local index variable */
456     size_t ret_value = 0;       /* Return value */
457 
458     FUNC_ENTER_NOAPI_NOINIT_NOERR
459 
460     /* Message header */
461     ret_value = 1 +			/*version			*/
462 	   1 +				/*number of filters		*/
463 	   (pline->version == H5O_PLINE_VERSION_1 ? 6 : 0);	/*reserved			*/
464 
465     /* Calculate size of each filter in pipeline */
466     for(i = 0; i < pline->nused; i++) {
467         size_t	name_len;               /* Length of filter name */
468         const char *name;               /* Filter name */
469 
470         /* Don't write the name length & name if the filter is an internal filter */
471         if(pline->version > H5O_PLINE_VERSION_1 && pline->filter[i].id < H5Z_FILTER_RESERVED)
472             name_len = 0;
473         else {
474             H5Z_class2_t	*cls;                   /* Filter class */
475 
476             /* Get the name of the filter, same as done with H5O_pline_encode() */
477             if(NULL == (name = pline->filter[i].name) && (cls = H5Z_find(pline->filter[i].id)))
478                 name = cls->name;
479             name_len = name ? HDstrlen(name) + 1 : 0;
480         } /* end else */
481 
482 	ret_value += 2 +			/*filter identification number	*/
483 		(size_t)((pline->version == H5O_PLINE_VERSION_1 || pline->filter[i].id >= H5Z_FILTER_RESERVED) ? 2 : 0) +				/*name length			*/
484 		2 +				/*flags				*/
485 		2 +				/*number of client data values	*/
486 		(pline->version == H5O_PLINE_VERSION_1 ? (size_t)H5O_ALIGN_OLD(name_len) : name_len);	/*length of the filter name	*/
487 
488 	ret_value += pline->filter[i].cd_nelmts * 4;
489         if(pline->version == H5O_PLINE_VERSION_1)
490             if(pline->filter[i].cd_nelmts % 2)
491                 ret_value += 4;
492     } /* end for */
493 
494     FUNC_LEAVE_NOAPI(ret_value)
495 } /* end H5O_pline_size() */
496 
497 
498 /*-------------------------------------------------------------------------
499  * Function:	H5O__pline_reset
500  *
501  * Purpose:	Resets a filter pipeline message by clearing all filters.
502  *		The MESG buffer is not freed.
503  *
504  * Return:	Non-negative on success/Negative on failure
505  *
506  * Programmer:	Robb Matzke
507  *              Wednesday, April 15, 1998
508  *
509  *-------------------------------------------------------------------------
510  */
511 static herr_t
H5O__pline_reset(void * mesg)512 H5O__pline_reset(void *mesg)
513 {
514     H5O_pline_t	*pline = (H5O_pline_t*)mesg;    /* Pipeline message */
515     size_t	i;                              /* Local index variable */
516 
517     FUNC_ENTER_STATIC_NOERR
518 
519     /* NOTE: This function can be called during error processing from
520      *       other API calls so DO NOT ASSUME THAT ANY VALUES ARE SANE.
521      */
522 
523     HDassert(pline);
524 
525     /* Free the filter information and array */
526     if (pline->filter) {
527 
528         /* Free information for each filter */
529         for(i = 0; i < pline->nused; i++) {
530             if(pline->filter[i].name && pline->filter[i].name != pline->filter[i]._name)
531                 HDassert((HDstrlen(pline->filter[i].name) + 1) > H5Z_COMMON_NAME_LEN);
532             if(pline->filter[i].name != pline->filter[i]._name)
533                 pline->filter[i].name = (char *)H5MM_xfree(pline->filter[i].name);
534             if(pline->filter[i].cd_values && pline->filter[i].cd_values != pline->filter[i]._cd_values)
535                 HDassert(pline->filter[i].cd_nelmts > H5Z_COMMON_CD_VALUES);
536             if(pline->filter[i].cd_values != pline->filter[i]._cd_values)
537                 pline->filter[i].cd_values = (unsigned *)H5MM_xfree(pline->filter[i].cd_values);
538         } /* end for */
539 
540         /* Free filter array */
541         pline->filter = (H5Z_filter_info_t *)H5MM_xfree(pline->filter);
542     }
543 
544     /* Reset # of filters */
545     pline->nused = pline->nalloc = 0;
546 
547     /* Reset version # of pipeline message */
548     pline->version = H5O_PLINE_VERSION_1;
549 
550     FUNC_LEAVE_NOAPI(SUCCEED)
551 } /* end H5O__pline_reset() */
552 
553 
554 /*-------------------------------------------------------------------------
555  * Function:	H5O__pline_free
556  *
557  * Purpose:	Frees the message
558  *
559  * Return:	Non-negative on success/Negative on failure
560  *
561  * Programmer:	Quincey Koziol
562  *              Saturday, March 11, 2000
563  *
564  *-------------------------------------------------------------------------
565  */
566 static herr_t
H5O__pline_free(void * mesg)567 H5O__pline_free(void *mesg)
568 {
569     FUNC_ENTER_STATIC_NOERR
570 
571     HDassert(mesg);
572 
573     mesg = H5FL_FREE(H5O_pline_t, mesg);
574 
575     FUNC_LEAVE_NOAPI(SUCCEED)
576 } /* end H5O__pline_free() */
577 
578 
579 /*-------------------------------------------------------------------------
580  * Function:    H5O_pline_pre_copy_file
581  *
582  * Purpose:     Perform any necessary actions before copying message between
583  *              files
584  *
585  * Return:      Success:        Non-negative
586  *
587  *              Failure:        Negative
588  *
589  * Programmer:  Peter Cao
590  *              December 27, 2005
591  *
592  *-------------------------------------------------------------------------
593  */
594 static herr_t
H5O_pline_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)595 H5O_pline_pre_copy_file(H5F_t H5_ATTR_UNUSED *file_src, const void *mesg_src,
596     hbool_t H5_ATTR_UNUSED *deleted, const H5O_copy_t *cpy_info, void *_udata)
597 {
598     const H5O_pline_t *pline_src = (const H5O_pline_t *)mesg_src;    /* Source pline */
599     H5O_copy_file_ud_common_t *udata = (H5O_copy_file_ud_common_t *)_udata; /* Object copying user data */
600     herr_t ret_value = SUCCEED;                                     /* Return value */
601 
602     FUNC_ENTER_NOAPI_NOINIT
603 
604     /* check args */
605     HDassert(pline_src);
606     HDassert(cpy_info);
607     HDassert(cpy_info->file_dst);
608 
609     /* Check to ensure that the version of the message to be copied does not exceed
610        the message version allowed by the destination file's high bound */
611     if(pline_src->version > H5O_pline_ver_bounds[H5F_HIGH_BOUND(cpy_info->file_dst)])
612         HGOTO_ERROR(H5E_OHDR, H5E_BADRANGE, FAIL, "pline message version out of bounds")
613 
614     /* If the user data is non-NULL, assume we are copying a dataset or group
615      * and make a copy of the filter pipeline for later in
616      * the object copying process.
617      */
618     if(udata)
619         if(NULL == (udata->src_pline = (H5O_pline_t *)H5O_pline_copy(pline_src, NULL)))
620             HGOTO_ERROR(H5E_PLINE, H5E_CANTINIT, FAIL, "unable to copy")
621 
622 done:
623     FUNC_LEAVE_NOAPI(ret_value)
624 } /* end H5O_pline_pre_copy_file() */
625 
626 
627 /*-------------------------------------------------------------------------
628  * Function:	H5O__pline_debug
629  *
630  * Purpose:	Prints debugging information for filter pipeline message MESG
631  *		on output stream STREAM.  Each line is indented INDENT
632  *		characters and the field name takes up FWIDTH characters.
633  *
634  * Return:	Non-negative on success/Negative on failure
635  *
636  * Programmer:	Robb Matzke
637  *              Wednesday, April 15, 1998
638  *
639  *-------------------------------------------------------------------------
640  */
641 static herr_t
H5O__pline_debug(H5F_t H5_ATTR_UNUSED * f,const void * mesg,FILE * stream,int indent,int fwidth)642 H5O__pline_debug(H5F_t H5_ATTR_UNUSED *f, const void *mesg, FILE *stream,
643     int indent, int fwidth)
644 {
645     const H5O_pline_t	*pline = (const H5O_pline_t *)mesg;
646     size_t		i, j;
647 
648     FUNC_ENTER_STATIC_NOERR
649 
650     /* check args */
651     HDassert(f);
652     HDassert(pline);
653     HDassert(stream);
654     HDassert(indent >= 0);
655     HDassert(fwidth >= 0);
656 
657     HDfprintf(stream, "%*s%-*s %Zu/%Zu\n", indent, "", fwidth,
658 	    "Number of filters:",
659 	    pline->nused,
660 	    pline->nalloc);
661 
662     /* Loop over all the filters */
663     for(i = 0; i < pline->nused; i++) {
664 	char		name[32];
665 
666 	HDsnprintf(name, sizeof(name), "Filter at position %u", (unsigned)i);
667 	HDfprintf(stream, "%*s%-*s\n", indent, "", fwidth, name);
668 	HDfprintf(stream, "%*s%-*s 0x%04x\n", indent + 3, "", MAX(0, fwidth - 3),
669 		"Filter identification:",
670 		(unsigned)(pline->filter[i].id));
671 	if(pline->filter[i].name)
672 	    HDfprintf(stream, "%*s%-*s \"%s\"\n", indent + 3, "", MAX(0, fwidth - 3),
673 		    "Filter name:",
674 		    pline->filter[i].name);
675 	else
676 	    HDfprintf(stream, "%*s%-*s NONE\n", indent + 3, "", MAX(0, fwidth - 3),
677 		    "Filter name:");
678 	HDfprintf(stream, "%*s%-*s 0x%04x\n", indent + 3, "", MAX(0, fwidth - 3),
679 		"Flags:",
680 		pline->filter[i].flags);
681 	HDfprintf(stream, "%*s%-*s %Zu\n", indent + 3, "", MAX(0, fwidth - 3),
682 		"Num CD values:",
683 		pline->filter[i].cd_nelmts);
684 
685         /* Filter parameters */
686 	for(j = 0; j < pline->filter[i].cd_nelmts; j++) {
687 	    char	field_name[32];
688 
689 	    HDsnprintf(field_name, sizeof(field_name), "CD value %lu", (unsigned long)j);
690 	    HDfprintf(stream, "%*s%-*s %u\n", indent + 6, "", MAX(0, fwidth - 6),
691 		    field_name,
692 		    pline->filter[i].cd_values[j]);
693 	} /* end for */
694     } /* end for */
695 
696     FUNC_LEAVE_NOAPI(SUCCEED)
697 } /* end H5O__pline_debug() */
698 
699 
700 /*-------------------------------------------------------------------------
701  * Function:    H5O_pline_set_version
702  *
703  * Purpose:     Set the version to encode an I/O filter pipeline with.
704  *
705  * Return:      Non-negative on success/Negative on failure
706  *
707  * Programmer:  Vailin Choi; December 2017
708  *
709  *-------------------------------------------------------------------------
710  */
711 herr_t
H5O_pline_set_version(H5F_t * f,H5O_pline_t * pline)712 H5O_pline_set_version(H5F_t *f, H5O_pline_t *pline)
713 {
714     unsigned version;           /* Message version */
715     herr_t ret_value = SUCCEED; /* Return value */
716 
717     FUNC_ENTER_NOAPI(FAIL)
718 
719     /* Sanity check */
720     HDassert(f);
721     HDassert(pline);
722 
723     /* Upgrade to the version indicated by the file's low bound if higher */
724     version = MAX(pline->version, H5O_pline_ver_bounds[H5F_LOW_BOUND(f)]);
725 
726     /* Version bounds check */
727     if(version > H5O_pline_ver_bounds[H5F_HIGH_BOUND(f)])
728         HGOTO_ERROR(H5E_PLINE, H5E_BADRANGE, FAIL, "Filter pipeline version out of bounds")
729 
730     /* Set the message version */
731     pline->version = version;
732 
733 done:
734     FUNC_LEAVE_NOAPI(ret_value)
735 } /* end H5O_pline_set_version() */
736