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 files COPYING and Copyright.html.  COPYING can be found at the root   *
9  * of the source code distribution tree; Copyright.html can be found at the  *
10  * root level of an installed copy of the electronic HDF5 document set and   *
11  * is linked from the top-level documents page.  It can also be found at     *
12  * http://hdfgroup.org/HDF5/doc/Copyright.html.  If you do not have          *
13  * access to either file, you may request a copy from help@hdfgroup.org.     *
14  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /*
17  * Programmer:  Robb Matzke <matzke@llnl.gov>
18  *              Monday, July 26, 1999
19  *
20  * Purpose:	The Virtual File Layer as described in documentation.
21  *              This is the greatest common denominator for all types of
22  *              storage access whether a file, memory, network, etc. This
23  *              layer usually just dispatches the request to an actual
24  *              file driver layer.
25  */
26 
27 /****************/
28 /* Module Setup */
29 /****************/
30 
31 #define H5F_PACKAGE		/*suppress error about including H5Fpkg	  */
32 #define H5FD_PACKAGE		/*suppress error about including H5FDpkg  */
33 
34 /* Interface initialization */
35 #define H5_INTERFACE_INIT_FUNC	H5FD_init_interface
36 
37 
38 /***********/
39 /* Headers */
40 /***********/
41 #include "H5private.h"		/* Generic Functions			*/
42 #include "H5Dprivate.h"		/* Datasets				*/
43 #include "H5Eprivate.h"		/* Error handling		  	*/
44 #include "H5Fpkg.h"             /* File access				*/
45 #include "H5FDpkg.h"		/* File Drivers				*/
46 #include "H5FDcore.h"		/* Files stored entirely in memory	*/
47 #include "H5FDfamily.h"		/* File families 			*/
48 #include "H5FDlog.h"        	/* sec2 driver with I/O logging (for debugging) */
49 #include "H5FDmpi.h"            /* MPI-based file drivers		*/
50 #include "H5FDmulti.h"		/* Usage-partitioned file family	*/
51 #include "H5FDsec2.h"		/* POSIX unbuffered file I/O		*/
52 #include "H5FDstdio.h"		/* Standard C buffered I/O		*/
53 #ifdef H5_HAVE_WINDOWS
54 #include "H5FDwindows.h"        /* Windows buffered I/O     */
55 #endif
56 #include "H5FDdirect.h"		/* Direct file I/O			*/
57 #include "H5Iprivate.h"		/* IDs			  		*/
58 #include "H5MMprivate.h"	/* Memory management			*/
59 #include "H5Pprivate.h"		/* Property lists			*/
60 
61 /****************/
62 /* Local Macros */
63 /****************/
64 
65 
66 /******************/
67 /* Local Typedefs */
68 /******************/
69 
70 
71 /********************/
72 /* Package Typedefs */
73 /********************/
74 
75 
76 /********************/
77 /* Local Prototypes */
78 /********************/
79 static herr_t H5FD_pl_copy(void *(*copy_func)(const void *), size_t pl_size,
80     const void *old_pl, void **copied_pl);
81 static herr_t H5FD_pl_close(hid_t driver_id, herr_t (*free_func)(void *),
82     void *pl);
83 static herr_t H5FD_free_cls(H5FD_class_t *cls);
84 static herr_t H5FD_fapl_copy(hid_t driver_id, const void *fapl, void **copied_fapl);
85 static int H5FD_query(const H5FD_t *f, unsigned long *flags/*out*/);
86 static int H5FD_driver_query(const H5FD_class_t *driver, unsigned long *flags/*out*/);
87 
88 /*********************/
89 /* Package Variables */
90 /*********************/
91 
92 
93 /*****************************/
94 /* Library Private Variables */
95 /*****************************/
96 
97 
98 /*******************/
99 /* Local Variables */
100 /*******************/
101 
102 /*
103  * Global count of the number of H5FD_t's handed out.  This is used as a
104  * "serial number" for files that are currently open and is used for the
105  * 'fileno' field in H5O_info_t.  However, if a VFL driver is not able
106  * to detect whether two files are the same, a file that has been opened
107  * by H5Fopen more than once with that VFL driver will have two different
108  * serial numbers.  :-/
109  *
110  * Also, if a file is opened, the 'fileno' field is retrieved for an
111  * object and the file is closed and re-opened, the 'fileno' value will
112  * be different.
113  */
114 static unsigned long file_serial_no;
115 
116 /* File driver ID class */
117 static const H5I_class_t H5I_VFL_CLS[1] = {{
118     H5I_VFL,			/* ID class value */
119     H5I_CLASS_REUSE_IDS,	/* Class flags */
120     0,				/* # of reserved IDs for class */
121     (H5I_free_t)H5FD_free_cls	/* Callback routine for closing objects of this class */
122 }};
123 
124 
125 
126 /*-------------------------------------------------------------------------
127  * Function:	H5FD_init
128  *
129  * Purpose:	Initialize the interface from some other package.
130  *
131  * Return:	Success:	non-negative
132  *		Failure:	negative
133  *
134  * Programmer:	Quincey Koziol
135  *              Thursday, January  3, 2007
136  *
137  *-------------------------------------------------------------------------
138  */
139 herr_t
H5FD_init(void)140 H5FD_init(void)
141 {
142     herr_t ret_value = SUCCEED;   /* Return value */
143 
144     FUNC_ENTER_NOAPI(FAIL)
145     /* FUNC_ENTER() does all the work */
146 
147 done:
148     FUNC_LEAVE_NOAPI(ret_value)
149 } /* end H5FD_init() */
150 
151 
152 /*-------------------------------------------------------------------------
153  * Function:	H5FD_init_interface
154  *
155  * Purpose:	Initialize the virtual file layer.
156  *
157  * Return:	Success:	Non-negative
158  *
159  *		Failure:	Negative
160  *
161  * Programmer:	Robb Matzke
162  *              Monday, July 26, 1999
163  *
164  * Modifications:
165  *
166  *-------------------------------------------------------------------------
167  */
168 static herr_t
H5FD_init_interface(void)169 H5FD_init_interface(void)
170 {
171     herr_t      ret_value = SUCCEED;       /* Return value */
172 
173     FUNC_ENTER_NOAPI_NOINIT
174 
175     if(H5I_register_type(H5I_VFL_CLS) < 0)
176 	HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "unable to initialize interface")
177 
178     /* Reset the file serial numbers */
179     file_serial_no = 0;
180 
181 done:
182     FUNC_LEAVE_NOAPI(ret_value)
183 } /* end H5FD_init_interface() */
184 
185 
186 /*-------------------------------------------------------------------------
187  * Function:	H5FD_term_interface
188  *
189  * Purpose:	Terminate this interface: free all memory and reset global
190  *		variables to their initial values.  Release all ID groups
191  *		associated with this interface.
192  *
193  * Return:	Success:	Positive if anything was done that might
194  *				have affected other interfaces; zero
195  *				otherwise.
196  *
197  *		Failure:        Never fails.
198  *
199  * Programmer:	Robb Matzke
200  *              Friday, February 19, 1999
201  *
202  * Modifications:
203  *
204  *-------------------------------------------------------------------------
205  */
206 int
H5FD_term_interface(void)207 H5FD_term_interface(void)
208 {
209     int	n = 0;
210 
211     FUNC_ENTER_NOAPI_NOINIT_NOERR
212 
213     if(H5_interface_initialize_g) {
214 	if((n=H5I_nmembers(H5I_VFL))!=0) {
215 	    H5I_clear_type(H5I_VFL, FALSE, FALSE);
216 
217             /* Reset the VFL drivers, if they've been closed */
218             if(H5I_nmembers(H5I_VFL)==0) {
219                 H5FD_sec2_term();
220 #ifdef H5_HAVE_DIRECT
221                 H5FD_direct_term();
222 #endif
223                 H5FD_log_term();
224                 H5FD_stdio_term();
225 #ifdef H5_HAVE_WINDOWS
226                 H5FD_windows_term();
227 #endif
228                 H5FD_family_term();
229                 H5FD_core_term();
230                 H5FD_multi_term();
231 #ifdef H5_HAVE_PARALLEL
232                 H5FD_mpio_term();
233 #endif /* H5_HAVE_PARALLEL */
234             } /* end if */
235 	} else {
236 	    H5I_dec_type_ref(H5I_VFL);
237 	    H5_interface_initialize_g = 0;
238 	    n = 1; /*H5I*/
239 	}
240     }
241     FUNC_LEAVE_NOAPI(n)
242 }
243 
244 
245 /*-------------------------------------------------------------------------
246  * Function:	H5FD_free_cls
247  *
248  * Purpose:	Frees a file driver class struct and returns an indication of
249  *		success. This function is used as the free callback for the
250  *		virtual file layer object identifiers (cf H5FD_init_interface).
251  *
252  * Return:	Success:	Non-negative
253  *
254  *		Failure:	Negative
255  *
256  * Programmer:	Robb Matzke
257  *              Monday, July 26, 1999
258  *
259  * Modifications:
260  *
261  *-------------------------------------------------------------------------
262  */
263 static herr_t
H5FD_free_cls(H5FD_class_t * cls)264 H5FD_free_cls(H5FD_class_t *cls)
265 {
266     FUNC_ENTER_NOAPI_NOINIT_NOERR
267 
268     H5MM_xfree(cls);
269 
270     FUNC_LEAVE_NOAPI(SUCCEED)
271 } /* end H5FD_free_cls() */
272 
273 
274 /*-------------------------------------------------------------------------
275  * Function:	H5FDregister
276  *
277  * Purpose:	Registers a new file driver as a member of the virtual file
278  *		driver class.  Certain fields of the class struct are
279  *		required and that is checked here so it doesn't have to be
280  *		checked every time the field is accessed.
281  *
282  * Return:	Success:	A file driver ID which is good until the
283  *				library is closed or the driver is
284  *				unregistered.
285  *
286  *		Failure:	A negative value.
287  *
288  * Programmer:	Robb Matzke
289  *              Monday, July 26, 1999
290  *
291  * Modifications:
292  *              Copied guts of function into H5FD_register
293  *              Quincey Koziol
294  *              Friday, January 30, 2004
295  *
296  *-------------------------------------------------------------------------
297  */
298 hid_t
H5FDregister(const H5FD_class_t * cls)299 H5FDregister(const H5FD_class_t *cls)
300 {
301     hid_t		ret_value;
302     H5FD_mem_t		type;
303 
304     FUNC_ENTER_API(FAIL)
305     H5TRACE1("i", "*x", cls);
306 
307     /* Check arguments */
308     if(!cls)
309 	HGOTO_ERROR(H5E_ARGS, H5E_UNINITIALIZED, FAIL, "null class pointer is disallowed")
310     if(!cls->open || !cls->close)
311 	HGOTO_ERROR(H5E_ARGS, H5E_UNINITIALIZED, FAIL, "`open' and/or `close' methods are not defined")
312     if(!cls->get_eoa || !cls->set_eoa)
313 	HGOTO_ERROR(H5E_ARGS, H5E_UNINITIALIZED, FAIL, "`get_eoa' and/or `set_eoa' methods are not defined")
314     if(!cls->get_eof)
315 	HGOTO_ERROR(H5E_ARGS, H5E_UNINITIALIZED, FAIL, "`get_eof' method is not defined")
316     if(!cls->read || !cls->write)
317 	HGOTO_ERROR(H5E_ARGS, H5E_UNINITIALIZED, FAIL, "`read' and/or `write' method is not defined")
318     for (type=H5FD_MEM_DEFAULT; type<H5FD_MEM_NTYPES; H5_INC_ENUM(H5FD_mem_t,type))
319 	if(cls->fl_map[type]<H5FD_MEM_NOLIST || cls->fl_map[type]>=H5FD_MEM_NTYPES)
320 	    HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid free-list mapping")
321 
322     /* Create the new class ID */
323     if((ret_value=H5FD_register(cls, sizeof(H5FD_class_t), TRUE)) < 0)
324         HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register file driver ID")
325 
326 done:
327     FUNC_LEAVE_API(ret_value)
328 } /* end H5FDregister() */
329 
330 
331 /*-------------------------------------------------------------------------
332  * Function:	H5FD_register
333  *
334  * Purpose:	Registers a new file driver as a member of the virtual file
335  *		driver class.  Certain fields of the class struct are
336  *		required and that is checked here so it doesn't have to be
337  *		checked every time the field is accessed.
338  *
339  * Return:	Success:	A file driver ID which is good until the
340  *				library is closed or the driver is
341  *				unregistered.
342  *
343  *		Failure:	A negative value.
344  *
345  * Programmer:	Robb Matzke
346  *              Monday, July 26, 1999
347  *
348  * Modifications:
349  *              Broke into public and internal routines & added 'size'
350  *              parameter to internal routine, which allows us to create
351  *              sub-classes of H5FD_class_t for internal support (see the
352  *              MPI drivers, etc.)
353  *              Quincey Koziol
354  *              January 30, 2004
355  *
356  *-------------------------------------------------------------------------
357  */
358 hid_t
H5FD_register(const void * _cls,size_t size,hbool_t app_ref)359 H5FD_register(const void *_cls, size_t size, hbool_t app_ref)
360 {
361     const H5FD_class_t	*cls = (const H5FD_class_t *)_cls;
362     H5FD_class_t	*saved = NULL;
363     H5FD_mem_t		type;
364     hid_t		ret_value;
365 
366     FUNC_ENTER_NOAPI(FAIL)
367 
368     /* Check arguments */
369     HDassert(cls);
370     HDassert(cls->open && cls->close);
371     HDassert(cls->get_eoa && cls->set_eoa);
372     HDassert(cls->get_eof);
373     HDassert(cls->read && cls->write);
374     for(type = H5FD_MEM_DEFAULT; type < H5FD_MEM_NTYPES; H5_INC_ENUM(H5FD_mem_t, type))
375         HDassert(cls->fl_map[type] >= H5FD_MEM_NOLIST && cls->fl_map[type] < H5FD_MEM_NTYPES);
376 
377     /* Copy the class structure so the caller can reuse or free it */
378     if(NULL == (saved = (H5FD_class_t *)H5MM_malloc(size)))
379 	HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for file driver class struct")
380     HDmemcpy(saved, cls, size);
381 
382     /* Create the new class ID */
383     if((ret_value = H5I_register(H5I_VFL, saved, app_ref)) < 0)
384         HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register file driver ID")
385 
386 done:
387     if(ret_value < 0)
388         if(saved)
389             H5MM_xfree(saved);
390 
391     FUNC_LEAVE_NOAPI(ret_value)
392 } /* end H5FD_register() */
393 
394 
395 /*-------------------------------------------------------------------------
396  * Function:	H5FDunregister
397  *
398  * Purpose:	Removes a driver ID from the library. This in no way affects
399  *		file access property lists which have been defined to use
400  *		this driver or files which are already opened under this
401  *		driver.
402  *
403  * Return:	Success:	Non-negative
404  *
405  *		Failure:	Negative
406  *
407  * Programmer:	Robb Matzke
408  *              Monday, July 26, 1999
409  *
410  *-------------------------------------------------------------------------
411  */
412 herr_t
H5FDunregister(hid_t driver_id)413 H5FDunregister(hid_t driver_id)
414 {
415     herr_t      ret_value = SUCCEED;       /* Return value */
416 
417     FUNC_ENTER_API(FAIL)
418     H5TRACE1("e", "i", driver_id);
419 
420     /* Check arguments */
421     if(NULL == H5I_object_verify(driver_id, H5I_VFL))
422 	HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file driver")
423 
424     /* The H5FD_class_t struct will be freed by this function */
425     if(H5I_dec_app_ref(driver_id) < 0)
426 	HGOTO_ERROR(H5E_VFL, H5E_CANTDEC, FAIL, "unable to unregister file driver")
427 
428 done:
429     FUNC_LEAVE_API(ret_value)
430 } /* end H5FDunregister() */
431 
432 
433 /*-------------------------------------------------------------------------
434  * Function:	H5FD_get_class
435  *
436  * Purpose:	Obtains a pointer to the driver struct containing all the
437  *		callback pointers, etc. The PLIST_ID argument can be a file
438  *		access property list, a data transfer property list, or a
439  *		file driver identifier.
440  *
441  * Return:	Success:	Ptr to the driver information. The pointer is
442  *				only valid as long as the driver remains
443  *				registered or some file or property list
444  *				exists which references the driver.
445  *
446  *		Failure:	NULL
447  *
448  * Programmer:	Robb Matzke
449  *              Friday, August 20, 1999
450  *
451  *-------------------------------------------------------------------------
452  */
453 H5FD_class_t *
H5FD_get_class(hid_t id)454 H5FD_get_class(hid_t id)
455 {
456     H5FD_class_t	*ret_value = NULL;
457 
458     FUNC_ENTER_NOAPI(NULL)
459 
460     if(H5I_VFL == H5I_get_type(id))
461 	ret_value = (H5FD_class_t *)H5I_object(id);
462     else {
463         H5P_genplist_t *plist;      /* Property list pointer */
464         hid_t driver_id = -1;
465 
466         /* Get the plist structure */
467         if(NULL == (plist = (H5P_genplist_t *)H5I_object(id)))
468             HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, NULL, "can't find object for ID")
469 
470         if(TRUE == H5P_isa_class(id, H5P_FILE_ACCESS)) {
471             if(H5P_get(plist, H5F_ACS_FILE_DRV_ID_NAME, &driver_id) < 0)
472                 HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get driver ID")
473             ret_value = H5FD_get_class(driver_id);
474         } /* end if */
475         else
476             HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a driver id or file access property list")
477     } /* end if */
478 
479 done:
480     FUNC_LEAVE_NOAPI(ret_value)
481 } /* end H5FD_get_class() */
482 
483 
484 /*-------------------------------------------------------------------------
485  * Function:	H5FD_sb_size
486  *
487  * Purpose:	Obtains the number of bytes required to store the driver file
488  *		access data in the HDF5 superblock.
489  *
490  * Return:	Success:	Number of bytes required.
491  *
492  *		Failure:	0 if an error occurs or if the driver has no
493  *				data to store in the superblock.
494  *
495  * Programmer:	Robb Matzke
496  *              Monday, August 16, 1999
497  *
498  * Modifications:
499  *
500  *-------------------------------------------------------------------------
501  */
502 hsize_t
H5FD_sb_size(H5FD_t * file)503 H5FD_sb_size(H5FD_t *file)
504 {
505     hsize_t	ret_value=0;
506 
507     FUNC_ENTER_NOAPI(0)
508 
509     HDassert(file && file->cls);
510 
511     if(file->cls->sb_size)
512 	ret_value = (file->cls->sb_size)(file);
513 
514 done:
515     FUNC_LEAVE_NOAPI(ret_value)
516 }
517 
518 
519 /*-------------------------------------------------------------------------
520  * Function:	H5FD_sb_encode
521  *
522  * Purpose:	Encode driver-specific data into the output arguments. The
523  *		NAME is a nine-byte buffer which should get an
524  *		eight-character driver name and/or version followed by a null
525  *		terminator. The BUF argument is a buffer to receive the
526  *		encoded driver-specific data. The size of the BUF array is
527  *		the size returned by the H5FD_sb_size() call.
528  *
529  * Return:	Success:	Non-negative
530  *
531  *		Failure:	Negative
532  *
533  * Programmer:	Robb Matzke
534  *              Monday, August 16, 1999
535  *
536  * Modifications:
537  *
538  *-------------------------------------------------------------------------
539  */
540 herr_t
H5FD_sb_encode(H5FD_t * file,char * name,uint8_t * buf)541 H5FD_sb_encode(H5FD_t *file, char *name/*out*/, uint8_t *buf)
542 {
543     herr_t      ret_value=SUCCEED;       /* Return value */
544 
545     FUNC_ENTER_NOAPI(FAIL)
546 
547     HDassert(file && file->cls);
548     if(file->cls->sb_encode &&
549             (file->cls->sb_encode)(file, name/*out*/, buf/*out*/) < 0)
550 	HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "driver sb_encode request failed")
551 
552 done:
553     FUNC_LEAVE_NOAPI(ret_value)
554 }
555 
556 
557 /*-------------------------------------------------------------------------
558  * Function:	H5FD_sb_decode
559  *
560  * Purpose:	Decodes the driver information block.
561  *
562  * Return:	Success:	Non-negative
563  *		Failure:	Negative
564  *
565  * Programmer:	Robb Matzke
566  *              Monday, August 16, 1999
567  *
568  *-------------------------------------------------------------------------
569  */
570 herr_t
H5FD_sb_decode(H5FD_t * file,const char * name,const uint8_t * buf)571 H5FD_sb_decode(H5FD_t *file, const char *name, const uint8_t *buf)
572 {
573     herr_t      ret_value = SUCCEED;    /* Return value */
574 
575     FUNC_ENTER_NOAPI(FAIL)
576 
577     HDassert(file && file->cls);
578     if(file->cls->sb_decode && (file->cls->sb_decode)(file, name, buf) < 0)
579 	HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "driver sb_decode request failed")
580 
581 done:
582     FUNC_LEAVE_NOAPI(ret_value)
583 } /* end H5FD_sb_decode() */
584 
585 
586 /*-------------------------------------------------------------------------
587  * Function:	H5FD_pl_copy
588  *
589  * Purpose:	Copies the driver-specific part of the a property list.
590  *              This is common code, used by both the dataset transfer and
591  *              file access property list routines.
592  *
593  * Return:	Success:	non-negative
594  *
595  *		Failure:	negative
596  *
597  * Programmer:	Quincey Koziol
598  *              Thursday, October 23, 2003
599  *
600  * Modifications:
601  *  Pedro Vicente Nunes, Wednesday, July 26, 2006
602  *  added a HGOTO_ERROR call in the case the copy function returns NULL
603  *
604  *-------------------------------------------------------------------------
605  */
606 static herr_t
H5FD_pl_copy(void * (* copy_func)(const void *),size_t pl_size,const void * old_pl,void ** copied_pl)607 H5FD_pl_copy(void *(*copy_func)(const void *), size_t pl_size, const void *old_pl, void **copied_pl)
608 {
609     void *new_pl = NULL;        /* Copy of property list */
610     herr_t ret_value=SUCCEED;   /* Return value */
611 
612     FUNC_ENTER_NOAPI_NOINIT
613 
614     /* Copy old pl, if one exists */
615     if(old_pl) {
616         /* Allow the driver to copy or do it ourselves */
617         if(copy_func) {
618             new_pl = (copy_func)(old_pl);
619             if(new_pl==NULL)
620                 HGOTO_ERROR(H5E_VFL, H5E_NOSPACE, FAIL, "property list copy failed")
621         } else if(pl_size>0) {
622             if((new_pl = H5MM_malloc(pl_size))==NULL)
623                 HGOTO_ERROR(H5E_VFL, H5E_NOSPACE, FAIL, "property list allocation failed")
624             HDmemcpy(new_pl, old_pl, pl_size);
625         } else
626             HGOTO_ERROR(H5E_VFL, H5E_UNSUPPORTED, FAIL, "no way to copy driver property list")
627     } /* end if */
628 
629     /* Set copied value */
630     *copied_pl=new_pl;
631 
632 done:
633     FUNC_LEAVE_NOAPI(ret_value)
634 } /* end H5FD_pl_copy() */
635 
636 
637 /*-------------------------------------------------------------------------
638  * Function:	H5FD_pl_close
639  *
640  * Purpose:	Closes a driver for a property list
641  *              This is common code, used by both the dataset transfer and
642  *              file access property list routines.
643  *
644  * Return:	Success:	non-negative
645  *		Failure:	negative
646  *
647  * Programmer:	Quincey Koziol
648  *              Thursday, October 23, 2003
649  *
650  *-------------------------------------------------------------------------
651  */
652 static herr_t
H5FD_pl_close(hid_t driver_id,herr_t (* free_func)(void *),void * pl)653 H5FD_pl_close(hid_t driver_id, herr_t (*free_func)(void *), void *pl)
654 {
655     herr_t ret_value = SUCCEED;         /* Return value */
656 
657     FUNC_ENTER_NOAPI_NOINIT
658 
659     /* Allow driver to free or do it ourselves */
660     if(pl && free_func) {
661 	if((free_func)(pl) < 0)
662 	    HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "driver free request failed")
663     } /* end if */
664     else
665 	H5MM_xfree(pl);
666 
667     /* Decrement reference count for driver */
668     if(H5I_dec_ref(driver_id) < 0)
669         HGOTO_ERROR(H5E_VFL, H5E_CANTDEC, FAIL, "can't decrement reference count for driver")
670 
671 done:
672     FUNC_LEAVE_NOAPI(ret_value)
673 } /* end H5FD_pl_close() */
674 
675 
676 /*-------------------------------------------------------------------------
677  * Function:	H5FD_fapl_get
678  *
679  * Purpose:	Gets the file access property list associated with a file.
680  *		Usually the file will copy what it needs from the original
681  *		file access property list when the file is created. The
682  *		purpose of this function is to create a new file access
683  *		property list based on the settings in the file, which may
684  *		have been modified from the original file access property
685  *		list.
686  *
687  * Return:	Success:	Pointer to a new file access property list
688  *				with all members copied.  If the file is
689  *				closed then this property list lives on, and
690  *				vice versa.
691  *
692  *		Failure:	NULL, including when the file has no
693  *				properties.
694  *
695  * Programmer:	Robb Matzke
696  *              Friday, August 13, 1999
697  *
698  * Modifications:
699  *
700  *-------------------------------------------------------------------------
701  */
702 void *
H5FD_fapl_get(H5FD_t * file)703 H5FD_fapl_get(H5FD_t *file)
704 {
705     void	*ret_value=NULL;
706 
707     FUNC_ENTER_NOAPI(NULL)
708 
709     HDassert(file);
710 
711     if(file->cls->fapl_get)
712 	ret_value = (file->cls->fapl_get)(file);
713 
714 done:
715     FUNC_LEAVE_NOAPI(ret_value)
716 } /* end H5FD_fapl_get() */
717 
718 
719 /*-------------------------------------------------------------------------
720  * Function:	H5FD_fapl_open
721  *
722  * Purpose:	Mark a driver as used by a file access property list
723  *
724  * Return:	Success:	non-negative
725  *
726  *		Failure:	negative
727  *
728  * Programmer:	Quincey Koziol
729  *              Thursday, October 23, 2003
730  *
731  * Modifications:
732  *
733  *-------------------------------------------------------------------------
734  */
735 herr_t
H5FD_fapl_open(H5P_genplist_t * plist,hid_t driver_id,const void * driver_info)736 H5FD_fapl_open(H5P_genplist_t *plist, hid_t driver_id, const void *driver_info)
737 {
738     void *copied_driver_info = NULL;           /* Temporary VFL driver info */
739     herr_t ret_value = SUCCEED;   /* Return value */
740 
741     FUNC_ENTER_NOAPI(FAIL)
742 
743     /* Increment the reference count on driver and copy driver info */
744     if(H5I_inc_ref(driver_id, FALSE) < 0)
745         HGOTO_ERROR(H5E_FILE, H5E_CANTINC, FAIL, "unable to increment ref count on VFL driver")
746     if(H5FD_fapl_copy(driver_id, driver_info, &copied_driver_info) < 0)
747         HGOTO_ERROR(H5E_FILE, H5E_CANTCOPY, FAIL, "can't copy VFL driver info")
748 
749     /* Set the driver properties for the list */
750     if(H5P_set(plist, H5F_ACS_FILE_DRV_ID_NAME, &driver_id) < 0)
751         HGOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "can't set driver ID")
752     if(H5P_set(plist, H5F_ACS_FILE_DRV_INFO_NAME, &copied_driver_info) < 0)
753         HGOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "can't set driver info")
754     copied_driver_info = NULL;
755 
756 done:
757     if(ret_value < 0)
758         if(copied_driver_info && H5FD_fapl_close(driver_id, copied_driver_info) < 0)
759             HDONE_ERROR(H5E_FILE, H5E_CANTCLOSEOBJ, FAIL, "can't close copy of driver info")
760 
761     FUNC_LEAVE_NOAPI(ret_value)
762 } /* end H5FD_fapl_open() */
763 
764 
765 /*-------------------------------------------------------------------------
766  * Function:	H5FD_fapl_copy
767  *
768  * Purpose:	Copies the driver-specific part of the file access property
769  *		list.
770  *
771  * Return:	Success:	non-negative
772  *
773  *		Failure:	negative
774  *
775  * Programmer:	Robb Matzke
776  *              Tuesday, August  3, 1999
777  *
778  *-------------------------------------------------------------------------
779  */
780 static herr_t
H5FD_fapl_copy(hid_t driver_id,const void * old_fapl,void ** copied_fapl)781 H5FD_fapl_copy(hid_t driver_id, const void *old_fapl, void **copied_fapl)
782 {
783     H5FD_class_t *driver;
784     herr_t ret_value = SUCCEED;       /* Return value */
785 
786     FUNC_ENTER_NOAPI_NOINIT
787 
788     /* Check args */
789     if(NULL == (driver = (H5FD_class_t *)H5I_object(driver_id)))
790 	HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a driver ID")
791 
792     /* Copy the file access property list */
793     if(H5FD_pl_copy(driver->fapl_copy, driver->fapl_size, old_fapl, copied_fapl) < 0)
794         HGOTO_ERROR(H5E_VFL, H5E_UNSUPPORTED, FAIL, "can't copy driver file access property list")
795 
796 done:
797     FUNC_LEAVE_NOAPI(ret_value)
798 }
799 
800 
801 /*-------------------------------------------------------------------------
802  * Function:	H5FD_fapl_close
803  *
804  * Purpose:	Closes a driver for a dataset transfer property list
805  *
806  * Return:	Success:	non-negative
807  *		Failure:	negative
808  *
809  * Programmer:	Robb Matzke
810  *              Tuesday, August  3, 1999
811  *
812  * Modifications:
813  *
814  *-------------------------------------------------------------------------
815  */
816 herr_t
H5FD_fapl_close(hid_t driver_id,void * fapl)817 H5FD_fapl_close(hid_t driver_id, void *fapl)
818 {
819     H5FD_class_t	*driver = NULL;
820     herr_t      ret_value = SUCCEED;       /* Return value */
821 
822     FUNC_ENTER_NOAPI(FAIL)
823 
824     /* Check args */
825     if(driver_id > 0) {
826         if(NULL == (driver = (H5FD_class_t *)H5I_object(driver_id)))
827             HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a driver ID")
828 
829         /* Close the driver for the property list */
830         if(H5FD_pl_close(driver_id, driver->fapl_free, fapl) < 0)
831             HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "driver fapl_free request failed")
832     } /* end if */
833 
834 done:
835     FUNC_LEAVE_NOAPI(ret_value)
836 } /* end H5FD_fapl_close() */
837 
838 
839 /*-------------------------------------------------------------------------
840  * Function:	H5FDopen
841  *
842  * Purpose:	Opens a file named NAME for the type(s) of access described
843  *		by the bit vector FLAGS according to a file access property
844  *		list FAPL_ID (which may be the constant H5P_DEFAULT). The
845  *		file should expect to handle format addresses in the range [0,
846  *		MAXADDR] (if MAXADDR is the undefined address then the caller
847  *		doesn't care about the address range).
848  *
849  * 		Possible values for the FLAGS bits are:
850  *
851  *		H5F_ACC_RDWR:	Open the file for read and write access. If
852  *				this bit is not set then open the file for
853  *				read only access. It is permissible to open a
854  *				file for read and write access when only read
855  *				access is requested by the library (the
856  *				library will never attempt to write to a file
857  *				which it opened with only read access).
858  *
859  *		H5F_ACC_CREATE:	Create the file if it doesn't already exist.
860  *				However, see H5F_ACC_EXCL below.
861  *
862  *		H5F_ACC_TRUNC:	Truncate the file if it already exists. This
863  *				is equivalent to deleting the file and then
864  *				creating a new empty file.
865  *
866  *		H5F_ACC_EXCL:	When used with H5F_ACC_CREATE, if the file
867  *				already exists then the open should fail.
868  *				Note that this is unsupported/broken with
869  *				some file drivers (e.g., sec2 across nfs) and
870  *				will contain a race condition when used to
871  *				perform file locking.
872  *
873  *		The MAXADDR is the maximum address which will be requested by
874  *		the library during an allocation operation. Usually this is
875  *		the same value as the MAXADDR field of the class structure,
876  *		but it can be smaller if the driver is being used under some
877  *		other driver.
878  *
879  *		Note that when the driver `open' callback gets control that
880  *		the public part of the file struct (the H5FD_t part) will be
881  *		incomplete and will be filled in after that callback returns.
882  *
883  * Return:	Success:	Pointer to a new file driver struct.
884  *
885  *		Failure:	NULL
886  *
887  * Programmer:	Robb Matzke
888  *              Tuesday, July 27, 1999
889  *
890  * Modifications:
891  *
892  *-------------------------------------------------------------------------
893  */
894 H5FD_t *
H5FDopen(const char * name,unsigned flags,hid_t fapl_id,haddr_t maxaddr)895 H5FDopen(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxaddr)
896 {
897     H5FD_t	*ret_value=NULL;
898 
899     FUNC_ENTER_API(NULL)
900 
901     /* Check arguments */
902     if(H5P_DEFAULT == fapl_id)
903         fapl_id = H5P_FILE_ACCESS_DEFAULT;
904     else
905         if(TRUE!=H5P_isa_class(fapl_id,H5P_FILE_ACCESS))
906             HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a file access property list")
907 
908     if(NULL==(ret_value=H5FD_open(name, flags, fapl_id, maxaddr)))
909 	HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, NULL, "unable to open file")
910 
911 done:
912     FUNC_LEAVE_API(ret_value)
913 }
914 
915 
916 /*-------------------------------------------------------------------------
917  * Function:	H5FD_open
918  *
919  * Purpose:	Private version of H5FDopen()
920  *
921  * Return:	Success:	Pointer to a new file driver struct
922  *
923  *		Failure:	NULL
924  *
925  * Programmer:	Robb Matzke
926  *              Wednesday, August  4, 1999
927  *
928  * Modifications:
929  *
930  *		Raymond Lu
931  * 		Tuesday, Oct 23, 2001
932  *		Changed the file access list to the new generic property
933  *		list.
934  *
935  *-------------------------------------------------------------------------
936  */
937 H5FD_t *
H5FD_open(const char * name,unsigned flags,hid_t fapl_id,haddr_t maxaddr)938 H5FD_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxaddr)
939 {
940     H5FD_class_t	*driver;                /* VFD for file */
941     H5FD_t		*file = NULL;           /* VFD file struct */
942     hid_t               driver_id = -1;         /* VFD ID */
943     H5P_genplist_t      *plist;                 /* Property list pointer */
944     unsigned long       driver_flags = 0;       /* File-inspecific driver feature flags */
945     H5FD_file_image_info_t file_image_info;     /* Initial file image */
946     H5FD_t		*ret_value;             /* Return value */
947 
948     FUNC_ENTER_NOAPI(NULL)
949 
950     /* Sanity check */
951     if(0 == maxaddr)
952 	HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "zero format address range")
953 
954     /* Get file access property list */
955     if(NULL == (plist = (H5P_genplist_t *)H5I_object(fapl_id)))
956         HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a file access property list")
957 
958     /* Get the VFD to open the file with */
959     if(H5P_get(plist, H5F_ACS_FILE_DRV_ID_NAME, &driver_id) < 0)
960         HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get driver ID")
961 
962     /* Get driver info */
963     if(NULL == (driver = (H5FD_class_t *)H5I_object(driver_id)))
964 	HGOTO_ERROR(H5E_VFL, H5E_BADVALUE, NULL, "invalid driver ID in file access property list")
965     if(NULL == driver->open)
966 	HGOTO_ERROR(H5E_VFL, H5E_UNSUPPORTED, NULL, "file driver has no `open' method")
967 
968     /* Query driver flag */
969     H5FD_driver_query(driver, &driver_flags);
970 
971     /* Get initial file image info */
972     if(H5P_get(plist, H5F_ACS_FILE_IMAGE_INFO_NAME, &file_image_info) < 0)
973         HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get file image info")
974 
975     /* If an image is provided, make sure the driver supports this feature */
976     HDassert(((file_image_info.buffer != NULL) && (file_image_info.size > 0)) ||
977              ((file_image_info.buffer == NULL) && (file_image_info.size == 0)));
978     if((file_image_info.buffer != NULL) && !(driver_flags & H5FD_FEAT_ALLOW_FILE_IMAGE))
979         HGOTO_ERROR(H5E_VFL, H5E_UNSUPPORTED, NULL, "file image set, but not supported.")
980 
981     /* Dispatch to file driver */
982     if(HADDR_UNDEF == maxaddr)
983         maxaddr = driver->maxaddr;
984     if(NULL == (file = (driver->open)(name, flags, fapl_id, maxaddr)))
985 	HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, NULL, "open failed")
986 
987     /*
988      * Fill in public fields. We must increment the reference count on the
989      * driver ID to prevent it from being freed while this file is open.
990      */
991     file->driver_id = driver_id;
992     if(H5I_inc_ref(file->driver_id, FALSE) < 0)
993         HGOTO_ERROR(H5E_VFL, H5E_CANTINC, NULL, "unable to increment ref count on VFL driver")
994     file->cls = driver;
995     file->maxaddr = maxaddr;
996     if(H5P_get(plist, H5F_ACS_ALIGN_THRHD_NAME, &(file->threshold)) < 0)
997         HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get alignment threshold")
998     if(H5P_get(plist, H5F_ACS_ALIGN_NAME, &(file->alignment)) < 0)
999         HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get alignment")
1000 
1001     /* Retrieve the VFL driver feature flags */
1002     if(H5FD_query(file, &(file->feature_flags)) < 0)
1003         HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, NULL, "unable to query file driver")
1004 
1005     /* Increment the global serial number & assign it to this H5FD_t object */
1006     if(++file_serial_no == 0) {
1007         /* (Just error out if we wrap around for now...) */
1008         HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, NULL, "unable to get file serial number")
1009     } /* end if */
1010     file->fileno = file_serial_no;
1011 
1012     /* Start with base address set to 0 */
1013     /* (This will be changed later, when the superblock is located) */
1014     file->base_addr = 0;
1015 
1016     /* Set return value */
1017     ret_value = file;
1018 
1019 done:
1020     /* Can't cleanup 'file' information, since we don't know what type it is */
1021     FUNC_LEAVE_NOAPI(ret_value)
1022 } /* end H5FD_open() */
1023 
1024 
1025 /*-------------------------------------------------------------------------
1026  * Function:	H5FDclose
1027  *
1028  * Purpose:     Closes the file by calling the driver `close' callback, which
1029  *		should free all driver-private data and free the file struct.
1030  *		Note that the public part of the file struct (the H5FD_t part)
1031  *		will be all zero during the driver close callback like during
1032  *		the `open' callback.
1033  *
1034  * Return:	Success:	Non-negative
1035  *		Failure:	Negative
1036  *
1037  * Programmer:	Robb Matzke
1038  *              Tuesday, July 27, 1999
1039  *
1040  *-------------------------------------------------------------------------
1041  */
1042 herr_t
H5FDclose(H5FD_t * file)1043 H5FDclose(H5FD_t *file)
1044 {
1045     herr_t      ret_value=SUCCEED;       /* Return value */
1046 
1047     FUNC_ENTER_API(FAIL)
1048     H5TRACE1("e", "*x", file);
1049 
1050     if(!file || !file->cls)
1051 	HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid file pointer")
1052 
1053     if(H5FD_close(file) < 0)
1054 	HGOTO_ERROR(H5E_VFL, H5E_CANTCLOSEFILE, FAIL, "unable to close file")
1055 
1056 done:
1057     FUNC_LEAVE_API(ret_value)
1058 } /* end H5FDclose() */
1059 
1060 
1061 /*-------------------------------------------------------------------------
1062  * Function:	H5FD_close
1063  *
1064  * Purpose:	Private version of H5FDclose()
1065  *
1066  * Return:	Success:	Non-negative
1067  *		Failure:	Negative
1068  *
1069  * Programmer:	Robb Matzke
1070  *              Wednesday, August  4, 1999
1071  *
1072  *-------------------------------------------------------------------------
1073  */
1074 herr_t
H5FD_close(H5FD_t * file)1075 H5FD_close(H5FD_t *file)
1076 {
1077     const H5FD_class_t *driver;
1078     herr_t              ret_value = SUCCEED;
1079 
1080     FUNC_ENTER_NOAPI(FAIL)
1081 
1082     /* check args */
1083     HDassert(file && file->cls);
1084 
1085     /* Prepare to close file by clearing all public fields */
1086     driver = file->cls;
1087     if(H5I_dec_ref(file->driver_id) < 0)
1088         HGOTO_ERROR(H5E_VFL, H5E_CANTDEC, FAIL, "can't close driver ID")
1089 
1090     /*
1091      * Dispatch to the driver for actual close. If the driver fails to
1092      * close the file then the file will be in an unusable state.
1093      */
1094     HDassert(driver->close);
1095     if((driver->close)(file) < 0)
1096         HGOTO_ERROR(H5E_VFL, H5E_CANTCLOSEFILE, FAIL, "close failed")
1097 
1098 done:
1099     FUNC_LEAVE_NOAPI(ret_value)
1100 } /* end H5FD_close() */
1101 
1102 
1103 /*-------------------------------------------------------------------------
1104  * Function:	H5FDcmp
1105  *
1106  * Purpose:	Compare the keys of two files using the file driver callback
1107  *		if the files belong to the same driver, otherwise sort the
1108  *		files by driver class pointer value.
1109  *
1110  * Return:	Success:	A value like strcmp()
1111  *
1112  *		Failure:	Must never fail. If both file handles are
1113  *				invalid then they compare equal. If one file
1114  *				handle is invalid then it compares less than
1115  *				the other.  If both files belong to the same
1116  *				driver and the driver doesn't provide a
1117  *				comparison callback then the file pointers
1118  *				themselves are compared.
1119  *
1120  * Programmer:	Robb Matzke
1121  *              Tuesday, July 27, 1999
1122  *
1123  * Modifications:
1124  *
1125  *-------------------------------------------------------------------------
1126  */
1127 int
H5FDcmp(const H5FD_t * f1,const H5FD_t * f2)1128 H5FDcmp(const H5FD_t *f1, const H5FD_t *f2)
1129 {
1130     int	ret_value;
1131 
1132     FUNC_ENTER_API(-1) /*return value is arbitrary*/
1133     H5TRACE2("Is", "*x*x", f1, f2);
1134 
1135     ret_value = H5FD_cmp(f1, f2);
1136 
1137 done:
1138     FUNC_LEAVE_API(ret_value)
1139 }
1140 
1141 
1142 /*-------------------------------------------------------------------------
1143  * Function:	H5FD_cmp
1144  *
1145  * Purpose:	Private version of H5FDcmp()
1146  *
1147  * Return:	Success:	A value like strcmp()
1148  *
1149  *		Failure:	Must never fail.
1150  *
1151  * Programmer:	Robb Matzke
1152  *              Wednesday, August  4, 1999
1153  *
1154  * Modifications:
1155  *
1156  *-------------------------------------------------------------------------
1157  */
1158 int
H5FD_cmp(const H5FD_t * f1,const H5FD_t * f2)1159 H5FD_cmp(const H5FD_t *f1, const H5FD_t *f2)
1160 {
1161     int	ret_value;
1162 
1163     FUNC_ENTER_NOAPI(-1) /*return value is arbitrary*/
1164 
1165     if((!f1 || !f1->cls) && (!f2 || !f2->cls))
1166         HGOTO_DONE(0)
1167     if(!f1 || !f1->cls)
1168         HGOTO_DONE(-1)
1169     if(!f2 || !f2->cls)
1170         HGOTO_DONE(1)
1171     if(f1->cls < f2->cls)
1172         HGOTO_DONE(-1)
1173     if(f1->cls > f2->cls)
1174         HGOTO_DONE(1)
1175 
1176     /* Files are same driver; no cmp callback */
1177     if(!f1->cls->cmp) {
1178 	if(f1<f2)
1179             HGOTO_DONE(-1)
1180 	if(f1>f2)
1181             HGOTO_DONE(1)
1182 	HGOTO_DONE(0)
1183     }
1184 
1185     ret_value = (f1->cls->cmp)(f1, f2);
1186 
1187 done:
1188     FUNC_LEAVE_NOAPI(ret_value)
1189 }
1190 
1191 
1192 /*-------------------------------------------------------------------------
1193  * Function:	H5FDquery
1194  *
1195  * Purpose:	Query a VFL driver for its feature flags. (listed in H5FDpublic.h)
1196  *
1197  * Return:	Success:    non-negative
1198  *
1199  *		Failure:	negative
1200  *
1201  * Programmer:	Quincey Koziol
1202  *              Friday, August 25, 2000
1203  *
1204  * Modifications:
1205  *
1206  *-------------------------------------------------------------------------
1207  */
1208 int
H5FDquery(const H5FD_t * f,unsigned long * flags)1209 H5FDquery(const H5FD_t *f, unsigned long *flags/*out*/)
1210 {
1211     int	ret_value;
1212 
1213     FUNC_ENTER_API(FAIL)
1214     H5TRACE2("Is", "*xx", f, flags);
1215 
1216     HDassert(f);
1217     HDassert(flags);
1218 
1219     ret_value = H5FD_query(f, flags);
1220 
1221 done:
1222     FUNC_LEAVE_API(ret_value)
1223 }
1224 
1225 
1226 /*-------------------------------------------------------------------------
1227  * Function:	H5FD_query
1228  *
1229  * Purpose:	Private version of H5FDquery()
1230  *
1231  * Return:	Success:    non-negative
1232  *
1233  *		Failure:	negative
1234  *
1235  * Programmer:	Quincey Koziol
1236  *              Friday, August 25, 2000
1237  *
1238  *-------------------------------------------------------------------------
1239  */
1240 static int
H5FD_query(const H5FD_t * f,unsigned long * flags)1241 H5FD_query(const H5FD_t *f, unsigned long *flags/*out*/)
1242 {
1243     int	ret_value = 0;          /* Return value */
1244 
1245     FUNC_ENTER_NOAPI_NOINIT_NOERR
1246 
1247     HDassert(f);
1248     HDassert(flags);
1249 
1250     /* Check for query driver and call it */
1251     if(f->cls->query)
1252         ret_value = (f->cls->query)(f, flags);
1253     else
1254         *flags=0;
1255 
1256     FUNC_LEAVE_NOAPI(ret_value)
1257 } /* end H5FD_query() */
1258 
1259 
1260 /*-------------------------------------------------------------------------
1261 * Function:    H5FD_driver_query
1262 *
1263 * Purpose: Similar to H5FD_query(), but intended for cases when we don't
1264 *          have a file available (e.g. before one is opened). Since we
1265 *          can't use the file to get the driver, the driver is passed in
1266 *          as a parameter.
1267 *
1268 * Return:  Success:    non-negative
1269 *          Failure:    negative
1270 *
1271 * Programmer:  Jacob Gruber
1272 *              Wednesday, August 17, 2011
1273 *
1274 *-------------------------------------------------------------------------
1275 */
1276 static int
H5FD_driver_query(const H5FD_class_t * driver,unsigned long * flags)1277 H5FD_driver_query(const H5FD_class_t *driver, unsigned long *flags/*out*/)
1278 {
1279     int ret_value = 0;          /* Return value */
1280 
1281     FUNC_ENTER_NOAPI_NOINIT_NOERR
1282 
1283     HDassert(driver);
1284     HDassert(flags);
1285 
1286     /* Check for the driver to query and then query it */
1287     if(driver->query)
1288         ret_value = (driver->query)(NULL, flags);
1289     else
1290         *flags = 0;
1291 
1292     FUNC_LEAVE_NOAPI(ret_value)
1293 } /* end H5FD_driver_query() */
1294 
1295 
1296 /*-------------------------------------------------------------------------
1297  * Function:	H5FDalloc
1298  *
1299  * Purpose:	Allocates SIZE bytes of memory from the FILE. The memory will
1300  *		be used according to the allocation class TYPE. First we try
1301  *		to satisfy the request from one of the free lists, according
1302  *		to the free list map provided by the driver. The free list
1303  *		array has one entry for each request type and the value of
1304  *		that array element can be one of four possibilities:
1305  *
1306  *		      It can be the constant H5FD_MEM_DEFAULT (or zero) which
1307  *		      indicates that the identity mapping is used. In other
1308  *		      words, the request type maps to its own free list.
1309  *
1310  *		      It can be the request type itself, which has the same
1311  *		      effect as the H5FD_MEM_DEFAULT value above.
1312  *
1313  *		      It can be the ID for another request type, which
1314  *		      indicates that the free list for the specified type
1315  *		      should be used instead.
1316  *
1317  *		      It can be the constant H5FD_MEM_NOLIST which means that
1318  *		      no free list should be used for this type of request.
1319  *
1320  *		If the request cannot be satisfied from a free list then
1321  *		either the driver's `alloc' callback is invoked (if one was
1322  *		supplied) or the end-of-address marker is extended. The
1323  *		`alloc' callback is always called with the same arguments as
1324  * 		the H5FDalloc().
1325  *
1326  * Return:	Success:	The format address of the new file memory.
1327  *
1328  *		Failure:	The undefined address HADDR_UNDEF
1329  *
1330  * Programmer:	Robb Matzke
1331  *              Tuesday, July 27, 1999
1332  *
1333  *-------------------------------------------------------------------------
1334  */
1335 haddr_t
H5FDalloc(H5FD_t * file,H5FD_mem_t type,hid_t dxpl_id,hsize_t size)1336 H5FDalloc(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, hsize_t size)
1337 {
1338     haddr_t	ret_value = HADDR_UNDEF;
1339 
1340     FUNC_ENTER_API(HADDR_UNDEF)
1341     H5TRACE4("a", "*xMtih", file, type, dxpl_id, size);
1342 
1343     /* Check args */
1344     if(!file || !file->cls)
1345 	HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, HADDR_UNDEF, "invalid file pointer")
1346     if(type < H5FD_MEM_DEFAULT || type >= H5FD_MEM_NTYPES)
1347 	HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, HADDR_UNDEF, "invalid request type")
1348     if(size == 0)
1349 	HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, HADDR_UNDEF, "zero-size request")
1350     if(H5P_DEFAULT == dxpl_id)
1351         dxpl_id = H5P_DATASET_XFER_DEFAULT;
1352     else
1353         if(TRUE != H5P_isa_class(dxpl_id, H5P_DATASET_XFER))
1354             HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, HADDR_UNDEF, "not a data transfer property list")
1355 
1356     /* Do the real work */
1357     if(HADDR_UNDEF == (ret_value = H5FD_alloc_real(file, dxpl_id, type, size, NULL, NULL)))
1358 	HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, HADDR_UNDEF, "unable to allocate file memory")
1359 
1360     /* (Note compensating for base address subtraction in internal routine) */
1361     ret_value += file->base_addr;
1362 
1363 done:
1364     FUNC_LEAVE_API(ret_value)
1365 } /* end H5FDalloc() */
1366 
1367 
1368 /*-------------------------------------------------------------------------
1369  * Function:	H5FDfree
1370  *
1371  * Purpose:	Frees format addresses starting with ADDR and continuing for
1372  *		SIZE bytes in the file FILE. The type of space being freed is
1373  *		specified by TYPE, which is mapped to a free list as
1374  *		described for the H5FDalloc() function above.  If the request
1375  *		doesn't map to a free list then either the application `free'
1376  *		callback is invoked (if defined) or the memory is leaked.
1377  *
1378  * Return:	Success:	Non-negative
1379  *
1380  *		Failure:	Negative
1381  *
1382  * Programmer:	Robb Matzke
1383  *              Wednesday, July 28, 1999
1384  *
1385  * Modifications:
1386  *
1387  *-------------------------------------------------------------------------
1388  */
1389 herr_t
H5FDfree(H5FD_t * file,H5FD_mem_t type,hid_t dxpl_id,haddr_t addr,hsize_t size)1390 H5FDfree(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, hsize_t size)
1391 {
1392     herr_t      ret_value=SUCCEED;       /* Return value */
1393 
1394     FUNC_ENTER_API(FAIL)
1395     H5TRACE5("e", "*xMtiah", file, type, dxpl_id, addr, size);
1396 
1397     /* Check args */
1398     if(!file || !file->cls)
1399         HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid file pointer")
1400     if(type < H5FD_MEM_DEFAULT || type >= H5FD_MEM_NTYPES)
1401         HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid request type")
1402     if(H5P_DEFAULT == dxpl_id)
1403         dxpl_id = H5P_DATASET_XFER_DEFAULT;
1404     else
1405         if(TRUE != H5P_isa_class(dxpl_id, H5P_DATASET_XFER))
1406             HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data transfer property list")
1407 
1408     /* Do the real work */
1409     /* (Note compensating for base address addition in internal routine) */
1410     if(H5FD_free_real(file, dxpl_id, type, addr - file->base_addr, size) < 0)
1411         HGOTO_ERROR(H5E_VFL, H5E_CANTFREE, FAIL, "file deallocation request failed")
1412 
1413 done:
1414     FUNC_LEAVE_API(ret_value)
1415 } /* end H5FDfree() */
1416 
1417 
1418 /*-------------------------------------------------------------------------
1419  * Function:	H5FDget_eoa
1420  *
1421  * Purpose:	Returns the address of the first byte after the last
1422  *		allocated memory in the file.
1423  *
1424  * Return:	Success:	First byte after allocated memory.
1425  *		Failure:	HADDR_UNDEF
1426  *
1427  * Programmer:	Robb Matzke
1428  *              Friday, July 30, 1999
1429  *
1430  *-------------------------------------------------------------------------
1431  */
1432 haddr_t
H5FDget_eoa(H5FD_t * file,H5FD_mem_t type)1433 H5FDget_eoa(H5FD_t *file, H5FD_mem_t type)
1434 {
1435     haddr_t	ret_value;
1436 
1437     FUNC_ENTER_API(HADDR_UNDEF)
1438     H5TRACE2("a", "*xMt", file, type);
1439 
1440     /* Check args */
1441     if(!file || !file->cls)
1442 	HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, HADDR_UNDEF, "invalid file pointer")
1443     if(type < H5FD_MEM_DEFAULT || type >= H5FD_MEM_NTYPES)
1444 	HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, HADDR_UNDEF, "invalid file type")
1445 
1446     /* The real work */
1447     if(HADDR_UNDEF == (ret_value = H5FD_get_eoa(file, type)))
1448 	HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, HADDR_UNDEF, "file get eoa request failed")
1449 
1450     /* (Note compensating for base address subtraction in internal routine) */
1451     ret_value += file->base_addr;
1452 
1453 done:
1454     FUNC_LEAVE_API(ret_value)
1455 } /* end H5FDget_eoa() */
1456 
1457 
1458 /*-------------------------------------------------------------------------
1459  * Function:	H5FDset_eoa
1460  *
1461  * Purpose:	Set the end-of-address marker for the file. The ADDR is the
1462  *		address of the first byte past the last allocated byte of the
1463  *		file. This function is called from two places:
1464  *
1465  *		    It is called after an existing file is opened in order to
1466  *		    "allocate" enough space to read the superblock and then
1467  *		    to "allocate" the entire hdf5 file based on the contents
1468  *		    of the superblock.
1469  *
1470  *		    It is called during file memory allocation if the
1471  *		    allocation request cannot be satisfied from the free list
1472  *		    and the driver didn't supply an allocation callback.
1473  *
1474  * Return:	Success:	Non-negative
1475  *		Failure:	Negative, no side effect
1476  *
1477  * Programmer:	Robb Matzke
1478  *              Friday, July 30, 1999
1479  *
1480  *-------------------------------------------------------------------------
1481  */
1482 herr_t
H5FDset_eoa(H5FD_t * file,H5FD_mem_t type,haddr_t addr)1483 H5FDset_eoa(H5FD_t *file, H5FD_mem_t type, haddr_t addr)
1484 {
1485     herr_t      ret_value = SUCCEED;       /* Return value */
1486 
1487     FUNC_ENTER_API(FAIL)
1488     H5TRACE3("e", "*xMta", file, type, addr);
1489 
1490     /* Check args */
1491     if(!file || !file->cls)
1492 	HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid file pointer")
1493     if(type < H5FD_MEM_DEFAULT || type >= H5FD_MEM_NTYPES)
1494 	HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid file type")
1495     if(!H5F_addr_defined(addr) || addr > file->maxaddr)
1496 	HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid end-of-address value")
1497 
1498     /* The real work */
1499     /* (Note compensating for base address addition in internal routine) */
1500     if(H5FD_set_eoa(file, type, addr - file->base_addr) < 0)
1501 	HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "file set eoa request failed")
1502 
1503 done:
1504     FUNC_LEAVE_API(ret_value)
1505 } /* end H5FDset_eoa() */
1506 
1507 
1508 /*-------------------------------------------------------------------------
1509  * Function:	H5FDget_eof
1510  *
1511  * Purpose:	Returns the end-of-file address, which is the greater of the
1512  *		end-of-format address and the actual EOF marker. This
1513  *		function is called after an existing file is opened in order
1514  *		for the library to learn the true size of the underlying file
1515  *		and to determine whether the hdf5 data has been truncated.
1516  *
1517  *		It is also used when a file is first opened to learn whether
1518  *		the file is empty or not.
1519  *
1520  * 		It is permissible for the driver to return the maximum address
1521  *		for the file size if the file is not empty.
1522  *
1523  * Return:	Success:	The EOF address.
1524  *
1525  *		Failure:	HADDR_UNDEF
1526  *
1527  * Programmer:	Robb Matzke
1528  *              Thursday, July 29, 1999
1529  *
1530  * Modifications:
1531  *
1532  *-------------------------------------------------------------------------
1533  */
1534 haddr_t
H5FDget_eof(H5FD_t * file)1535 H5FDget_eof(H5FD_t *file)
1536 {
1537     haddr_t	ret_value;
1538 
1539     FUNC_ENTER_API(HADDR_UNDEF)
1540     H5TRACE1("a", "*x", file);
1541 
1542     /* Check arguments */
1543     if(!file || !file->cls)
1544 	HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, HADDR_UNDEF, "invalid file pointer")
1545 
1546     /* The real work */
1547     if(HADDR_UNDEF == (ret_value = H5FD_get_eof(file)))
1548 	HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, HADDR_UNDEF, "file get eof request failed")
1549 
1550     /* (Note compensating for base address subtraction in internal routine) */
1551     ret_value += file->base_addr;
1552 
1553 done:
1554     FUNC_LEAVE_API(ret_value)
1555 } /* end H5FDget_eof() */
1556 
1557 
1558 /*-------------------------------------------------------------------------
1559  * Function:	H5FD_get_maxaddr
1560  *
1561  * Purpose:	Private version of H5FDget_eof()
1562  *
1563  * Return:	Success:	The maximum address allowed in the file.
1564  *		Failure:	HADDR_UNDEF
1565  *
1566  * Programmer:	Quincey Koziol
1567  *              Thursday, January  3, 2008
1568  *
1569  *-------------------------------------------------------------------------
1570  */
1571 haddr_t
H5FD_get_maxaddr(const H5FD_t * file)1572 H5FD_get_maxaddr(const H5FD_t *file)
1573 {
1574     haddr_t ret_value;          /* Return value */
1575 
1576     FUNC_ENTER_NOAPI(HADDR_UNDEF)
1577 
1578     HDassert(file);
1579 
1580     /* Set return value */
1581     ret_value = file->maxaddr;
1582 
1583 done:
1584     FUNC_LEAVE_NOAPI(ret_value)
1585 } /* end H5FD_get_maxaddr() */
1586 
1587 
1588 /*-------------------------------------------------------------------------
1589  * Function:	H5FD_get_feature_flags
1590  *
1591  * Purpose:	Retrieve the feature flags for the VFD
1592  *
1593  * Return:	Success:	Non-negative
1594  *		Failure:	Negative
1595  *
1596  * Programmer:	Quincey Koziol
1597  *              Tuesday, January  8, 2008
1598  *
1599  *-------------------------------------------------------------------------
1600  */
1601 herr_t
H5FD_get_feature_flags(const H5FD_t * file,unsigned long * feature_flags)1602 H5FD_get_feature_flags(const H5FD_t *file, unsigned long *feature_flags)
1603 {
1604     FUNC_ENTER_NOAPI_NOINIT_NOERR
1605 
1606     HDassert(file);
1607     HDassert(feature_flags);
1608 
1609     /* Set feature flags to return */
1610     *feature_flags = file->feature_flags;
1611 
1612     FUNC_LEAVE_NOAPI(SUCCEED)
1613 } /* end H5FD_get_feature_flags() */
1614 
1615 
1616 /*-------------------------------------------------------------------------
1617  * Function:	H5FD_get_fs_type_map
1618  *
1619  * Purpose:	Retrieve the free space type mapping for the VFD
1620  *
1621  * Return:	Success:	Non-negative
1622  *		Failure:	Negative
1623  *
1624  * Programmer:	Quincey Koziol
1625  *              Thursday, January 17, 2008
1626  *
1627  *-------------------------------------------------------------------------
1628  */
1629 herr_t
H5FD_get_fs_type_map(const H5FD_t * file,H5FD_mem_t * type_map)1630 H5FD_get_fs_type_map(const H5FD_t *file, H5FD_mem_t *type_map)
1631 {
1632     herr_t ret_value = SUCCEED;         /* Return value */
1633 
1634     FUNC_ENTER_NOAPI(FAIL)
1635 
1636     /* Sanity check */
1637     HDassert(file && file->cls);
1638     HDassert(type_map);
1639 
1640     /* Check for VFD class providing a type map retrieval rouine */
1641     if(file->cls->get_type_map) {
1642         /* Retrieve type mapping for this file */
1643         if((file->cls->get_type_map)(file, type_map) < 0)
1644             HGOTO_ERROR(H5E_VFL, H5E_CANTGET, FAIL, "driver get type map failed")
1645     } /* end if */
1646     else
1647         /* Copy class's default free space type mapping */
1648         HDmemcpy(type_map, file->cls->fl_map, sizeof(file->cls->fl_map));
1649 
1650 done:
1651     FUNC_LEAVE_NOAPI(ret_value)
1652 } /* end H5FD_get_fs_type_map() */
1653 
1654 
1655 /*-------------------------------------------------------------------------
1656  * Function:	H5FDread
1657  *
1658  * Purpose:	Reads SIZE bytes from FILE beginning at address ADDR
1659  *		according to the data transfer property list DXPL_ID (which may
1660  *		be the constant H5P_DEFAULT). The result is written into the
1661  *		buffer BUF.
1662  *
1663  * Return:	Success:	Non-negative. The read result is written into
1664  *				the BUF buffer which should be allocated by
1665  *				the caller.
1666  *
1667  *		Failure:	Negative. The contents of BUF is undefined.
1668  *
1669  * Programmer:	Robb Matzke
1670  *              Thursday, July 29, 1999
1671  *
1672  * Modifications:
1673  *
1674  *-------------------------------------------------------------------------
1675  */
1676 herr_t
H5FDread(H5FD_t * file,H5FD_mem_t type,hid_t dxpl_id,haddr_t addr,size_t size,void * buf)1677 H5FDread(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, size_t size,
1678 	 void *buf/*out*/)
1679 {
1680     herr_t      ret_value = SUCCEED;       /* Return value */
1681 
1682     FUNC_ENTER_API(FAIL)
1683     H5TRACE6("e", "*xMtiazx", file, type, dxpl_id, addr, size, buf);
1684 
1685     /* Check args */
1686     if(!file || !file->cls)
1687 	HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid file pointer")
1688 
1689     /* Get the default dataset transfer property list if the user didn't provide one */
1690     if(H5P_DEFAULT == dxpl_id)
1691         dxpl_id = H5P_DATASET_XFER_DEFAULT;
1692     else
1693         if(TRUE != H5P_isa_class(dxpl_id, H5P_DATASET_XFER))
1694             HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data transfer property list")
1695     if(!buf)
1696 	HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "null result buffer")
1697 
1698     /* Do the real work */
1699     /* (Note compensating for base address addition in internal routine) */
1700     if(H5FD_read(file, dxpl_id, type, addr - file->base_addr, size, buf) < 0)
1701 	HGOTO_ERROR(H5E_VFL, H5E_READERROR, FAIL, "file read request failed")
1702 
1703 done:
1704     FUNC_LEAVE_API(ret_value)
1705 } /* end H5FDread() */
1706 
1707 
1708 /*-------------------------------------------------------------------------
1709  * Function:	H5FDwrite
1710  *
1711  * Purpose:	Writes SIZE bytes to FILE beginning at address ADDR according
1712  *		to the data transfer property list DXPL_ID (which may be the
1713  *		constant H5P_DEFAULT). The bytes to be written come from the
1714  *		buffer BUF.
1715  *
1716  * Return:	Success:	Non-negative
1717  *
1718  *		Failure:	Negative
1719  *
1720  * Programmer:	Robb Matzke
1721  *              Thursday, July 29, 1999
1722  *
1723  * Modifications:
1724  *
1725  *-------------------------------------------------------------------------
1726  */
1727 herr_t
H5FDwrite(H5FD_t * file,H5FD_mem_t type,hid_t dxpl_id,haddr_t addr,size_t size,const void * buf)1728 H5FDwrite(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, size_t size,
1729 	  const void *buf)
1730 {
1731     herr_t      ret_value = SUCCEED;       /* Return value */
1732 
1733     FUNC_ENTER_API(FAIL)
1734     H5TRACE6("e", "*xMtiaz*x", file, type, dxpl_id, addr, size, buf);
1735 
1736     /* Check args */
1737     if(!file || !file->cls)
1738 	HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid file pointer")
1739     /* Get the default dataset transfer property list if the user didn't provide one */
1740     if(H5P_DEFAULT == dxpl_id)
1741         dxpl_id = H5P_DATASET_XFER_DEFAULT;
1742     else
1743         if(TRUE != H5P_isa_class(dxpl_id, H5P_DATASET_XFER))
1744             HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data transfer property list")
1745     if(!buf)
1746 	HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "null buffer")
1747 
1748     /* The real work */
1749     /* (Note compensating for base address addition in internal routine) */
1750     if(H5FD_write(file, dxpl_id, type, addr - file->base_addr, size, buf) < 0)
1751 	HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, FAIL, "file write request failed")
1752 
1753 done:
1754     FUNC_LEAVE_API(ret_value)
1755 } /* end H5FDwrite() */
1756 
1757 
1758 /*-------------------------------------------------------------------------
1759  * Function:	H5FDflush
1760  *
1761  * Purpose:	Notify driver to flush all cached data.  If the driver has no
1762  *		flush method then nothing happens.
1763  *
1764  * Return:	Success:	Non-negative
1765  *
1766  *		Failure:	Negative
1767  *
1768  * Programmer:	Robb Matzke
1769  *              Thursday, July 29, 1999
1770  *
1771  * Modifications:
1772  *              Quincey Koziol, May 20, 2002
1773  *              Added 'closing' parameter
1774  *
1775  *-------------------------------------------------------------------------
1776  */
1777 herr_t
H5FDflush(H5FD_t * file,hid_t dxpl_id,unsigned closing)1778 H5FDflush(H5FD_t *file, hid_t dxpl_id, unsigned closing)
1779 {
1780     herr_t ret_value = SUCCEED;       /* Return value */
1781 
1782     FUNC_ENTER_API(FAIL)
1783     H5TRACE3("e", "*xiIu", file, dxpl_id, closing);
1784 
1785     /* Check args */
1786     if(!file || !file->cls)
1787 	HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid file pointer")
1788     if(H5P_DEFAULT == dxpl_id)
1789         dxpl_id = H5P_DATASET_XFER_DEFAULT;
1790     else
1791         if(TRUE != H5P_isa_class(dxpl_id, H5P_DATASET_XFER))
1792             HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data transfer property list")
1793 
1794     /* Do the real work */
1795     if(H5FD_flush(file, dxpl_id, closing) < 0)
1796 	HGOTO_ERROR(H5E_VFL, H5E_CANTFLUSH, FAIL, "file flush request failed")
1797 
1798 done:
1799     FUNC_LEAVE_API(ret_value)
1800 }
1801 
1802 
1803 /*-------------------------------------------------------------------------
1804  * Function:	H5FD_flush
1805  *
1806  * Purpose:	Private version of H5FDflush()
1807  *
1808  * Return:	Success:	Non-negative
1809  *		Failure:	Negative
1810  *
1811  * Programmer:	Robb Matzke
1812  *              Wednesday, August  4, 1999
1813  *
1814  *-------------------------------------------------------------------------
1815  */
1816 herr_t
H5FD_flush(H5FD_t * file,hid_t dxpl_id,unsigned closing)1817 H5FD_flush(H5FD_t *file, hid_t dxpl_id, unsigned closing)
1818 {
1819     herr_t      ret_value = SUCCEED;       /* Return value */
1820 
1821     FUNC_ENTER_NOAPI(FAIL)
1822 
1823     HDassert(file && file->cls);
1824 
1825     if(file->cls->flush && (file->cls->flush)(file, dxpl_id, closing) < 0)
1826         HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "driver flush request failed")
1827 
1828 done:
1829     FUNC_LEAVE_NOAPI(ret_value)
1830 } /* end H5FD_flush() */
1831 
1832 
1833 /*-------------------------------------------------------------------------
1834  * Function:	H5FDtruncate
1835  *
1836  * Purpose:	Notify driver to truncate the file back to the allocated size.
1837  *
1838  * Return:	Success:	Non-negative
1839  *		Failure:	Negative
1840  *
1841  * Programmer:	Quincey Koziol
1842  *              Thursday, January 31, 2008
1843  *
1844  *-------------------------------------------------------------------------
1845  */
1846 herr_t
H5FDtruncate(H5FD_t * file,hid_t dxpl_id,unsigned closing)1847 H5FDtruncate(H5FD_t *file, hid_t dxpl_id, unsigned closing)
1848 {
1849     herr_t ret_value = SUCCEED;       /* Return value */
1850 
1851     FUNC_ENTER_API(FAIL)
1852     H5TRACE3("e", "*xiIu", file, dxpl_id, closing);
1853 
1854     /* Check args */
1855     if(!file || !file->cls)
1856 	HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid file pointer")
1857     if(H5P_DEFAULT == dxpl_id)
1858         dxpl_id = H5P_DATASET_XFER_DEFAULT;
1859     else
1860         if(TRUE != H5P_isa_class(dxpl_id, H5P_DATASET_XFER))
1861             HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data transfer property list")
1862 
1863     /* Do the real work */
1864     if(H5FD_truncate(file, dxpl_id, closing) < 0)
1865 	HGOTO_ERROR(H5E_VFL, H5E_CANTUPDATE, FAIL, "file flush request failed")
1866 
1867 done:
1868     FUNC_LEAVE_API(ret_value)
1869 }
1870 
1871 
1872 /*-------------------------------------------------------------------------
1873  * Function:	H5FD_truncate
1874  *
1875  * Purpose:	Private version of H5FDtruncate()
1876  *
1877  * Return:	Success:	Non-negative
1878  *		Failure:	Negative
1879  *
1880  * Programmer:	Quincey Koziol
1881  *              Thursday, January 31, 2008
1882  *
1883  *-------------------------------------------------------------------------
1884  */
1885 herr_t
H5FD_truncate(H5FD_t * file,hid_t dxpl_id,unsigned closing)1886 H5FD_truncate(H5FD_t *file, hid_t dxpl_id, unsigned closing)
1887 {
1888     herr_t      ret_value = SUCCEED;       /* Return value */
1889 
1890     FUNC_ENTER_NOAPI(FAIL)
1891 
1892     HDassert(file && file->cls);
1893 
1894     if(file->cls->truncate && (file->cls->truncate)(file, dxpl_id, closing) < 0)
1895         HGOTO_ERROR(H5E_VFL, H5E_CANTUPDATE, FAIL, "driver truncate request failed")
1896 
1897 done:
1898     FUNC_LEAVE_NOAPI(ret_value)
1899 } /* end H5FD_truncate() */
1900 
1901 
1902 /*-------------------------------------------------------------------------
1903  * Function:	H5FD_get_fileno
1904  *
1905  * Purpose:	Quick and dirty routine to retrieve the file's 'fileno' value
1906  *          (Mainly added to stop non-file routines from poking about in the
1907  *          H5FD_t data structure)
1908  *
1909  * Return:	Non-negative on success/Negative on failure
1910  *
1911  * Programmer:	Quincey Koziol <koziol@ncsa.uiuc.edu>
1912  *		March 27, 2002
1913  *
1914  *-------------------------------------------------------------------------
1915  */
1916 herr_t
H5FD_get_fileno(const H5FD_t * file,unsigned long * filenum)1917 H5FD_get_fileno(const H5FD_t *file, unsigned long *filenum)
1918 {
1919     FUNC_ENTER_NOAPI_NOINIT_NOERR
1920 
1921     HDassert(file);
1922     HDassert(filenum);
1923 
1924     /* Retrieve the file's serial number */
1925     *filenum = file->fileno;
1926 
1927     FUNC_LEAVE_NOAPI(SUCCEED)
1928 } /* end H5FD_get_fileno() */
1929 
1930 
1931 /*--------------------------------------------------------------------------
1932  * Function:    H5FDget_vfd_handle
1933  *
1934  * Purpose:     Returns a pointer to the file handle of low-level virtual
1935  *              file driver.
1936  *
1937  * Return:      Non-negative if succeed; negative otherwise.
1938  *
1939  * Programmer:  Raymond Lu
1940  *              Sep. 16, 2002
1941  *
1942  * Modifications:
1943  *
1944  *--------------------------------------------------------------------------
1945  */
1946 herr_t
H5FDget_vfd_handle(H5FD_t * file,hid_t fapl,void ** file_handle)1947 H5FDget_vfd_handle(H5FD_t *file, hid_t fapl, void **file_handle)
1948 {
1949     herr_t              ret_value;
1950 
1951     FUNC_ENTER_API(FAIL)
1952     H5TRACE3("e", "*xi**x", file, fapl, file_handle);
1953 
1954     /* Check arguments */
1955     HDassert(file);
1956     HDassert(file_handle);
1957 
1958     ret_value = H5FD_get_vfd_handle(file, fapl, file_handle);
1959 
1960 done:
1961     FUNC_LEAVE_API(ret_value)
1962 } /* end H5FDget_vfd_handle() */
1963 
1964 
1965 /*--------------------------------------------------------------------------
1966  * Function:    H5FD_get_vfd_handle
1967  *
1968  * Purpose:     Retrieve the file handle for file driver.
1969  *
1970  * Return:      Non-negative if succeed; negative if fails.
1971  *
1972  * Programmer:  Raymond Lu
1973  *              Sep. 16, 2002
1974  *
1975  *--------------------------------------------------------------------------
1976  */
1977 herr_t
H5FD_get_vfd_handle(H5FD_t * file,hid_t fapl,void ** file_handle)1978 H5FD_get_vfd_handle(H5FD_t *file, hid_t fapl, void **file_handle)
1979 {
1980     herr_t ret_value = SUCCEED;
1981 
1982     FUNC_ENTER_NOAPI(FAIL)
1983 
1984     /* Sanity check */
1985     HDassert(file);
1986     HDassert(file_handle);
1987 
1988     if(NULL == file->cls->get_handle)
1989 	HGOTO_ERROR(H5E_VFL, H5E_UNSUPPORTED, FAIL, "file driver has no `get_vfd_handle' method")
1990     if((file->cls->get_handle)(file, fapl, file_handle) < 0)
1991         HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't get file handle for file driver")
1992 
1993 done:
1994     FUNC_LEAVE_NOAPI(ret_value)
1995 } /* end H5FD_get_vfd_handle() */
1996 
1997 
1998 /*--------------------------------------------------------------------------
1999  * Function:    H5FD_set_base_addr
2000  *
2001  * Purpose:     Set the base address for the file
2002  *
2003  * Return:      Non-negative if succeed; negative if fails.
2004  *
2005  * Programmer:  Quincey Koziol
2006  *              Jan. 17, 2008
2007  *
2008  *--------------------------------------------------------------------------
2009  */
2010 herr_t
H5FD_set_base_addr(H5FD_t * file,haddr_t base_addr)2011 H5FD_set_base_addr(H5FD_t *file, haddr_t base_addr)
2012 {
2013     FUNC_ENTER_NOAPI_NOINIT_NOERR
2014 
2015     HDassert(file);
2016     HDassert(H5F_addr_defined(base_addr));
2017 
2018     /* Set the file's base address */
2019     file->base_addr = base_addr;
2020 
2021     FUNC_LEAVE_NOAPI(SUCCEED)
2022 } /* end H5FD_set_base_addr() */
2023 
2024 
2025 /*--------------------------------------------------------------------------
2026  * Function:    H5FD_get_base_addr
2027  *
2028  * Purpose:     Get the base address for the file
2029  *
2030  * Return:	Success:	The absolute base address of the file
2031  *		Failure:	The undefined address (HADDR_UNDEF)
2032  *
2033  * Programmer:  Quincey Koziol
2034  *              Sept. 10, 2009
2035  *
2036  *--------------------------------------------------------------------------
2037  */
2038 haddr_t
H5FD_get_base_addr(const H5FD_t * file)2039 H5FD_get_base_addr(const H5FD_t *file)
2040 {
2041     FUNC_ENTER_NOAPI_NOINIT_NOERR
2042 
2043     HDassert(file);
2044 
2045     /* Return the file's base address */
2046     FUNC_LEAVE_NOAPI(file->base_addr)
2047 } /* end H5FD_get_base_addr() */
2048 
2049