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  *
16  * Created:		H5FDint.c
17  *			Jan 17 2008
18  *			Quincey Koziol <koziol@hdfgroup.org>
19  *
20  * Purpose:		Internal routine for VFD operations
21  *
22  *-------------------------------------------------------------------------
23  */
24 
25 /****************/
26 /* Module Setup */
27 /****************/
28 
29 #define H5FD_PACKAGE		/*suppress error about including H5FDpkg  */
30 
31 /* Interface initialization */
32 #define H5_INTERFACE_INIT_FUNC	H5FD_int_init_interface
33 
34 
35 /***********/
36 /* Headers */
37 /***********/
38 #include "H5private.h"		/* Generic Functions			*/
39 #include "H5Eprivate.h"		/* Error handling		  	*/
40 #include "H5Fprivate.h"         /* File access				*/
41 #include "H5FDpkg.h"		/* File Drivers				*/
42 #include "H5Iprivate.h"		/* IDs			  		*/
43 
44 
45 /****************/
46 /* Local Macros */
47 /****************/
48 
49 
50 /******************/
51 /* Local Typedefs */
52 /******************/
53 
54 
55 /********************/
56 /* Package Typedefs */
57 /********************/
58 
59 
60 /********************/
61 /* Local Prototypes */
62 /********************/
63 
64 
65 /*********************/
66 /* Package Variables */
67 /*********************/
68 
69 
70 /*****************************/
71 /* Library Private Variables */
72 /*****************************/
73 
74 
75 /*******************/
76 /* Local Variables */
77 /*******************/
78 
79 
80 
81 /*--------------------------------------------------------------------------
82 NAME
83    H5FD_int_init_interface -- Initialize interface-specific information
84 USAGE
85     herr_t H5FD_int_init_interface()
86 
87 RETURNS
88     Non-negative on success/Negative on failure
89 DESCRIPTION
90     Initializes any interface-specific data or routines.  (Just calls
91     H5FD_init_iterface currently).
92 
93 --------------------------------------------------------------------------*/
94 static herr_t
H5FD_int_init_interface(void)95 H5FD_int_init_interface(void)
96 {
97     FUNC_ENTER_NOAPI_NOINIT_NOERR
98 
99     FUNC_LEAVE_NOAPI(H5FD_init())
100 } /* H5FD_int_init_interface() */
101 
102 
103 /*-------------------------------------------------------------------------
104  * Function:    H5FD_locate_signature
105  *
106  * Purpose:     Finds the HDF5 superblock signature in a file.  The
107  *              signature can appear at address 0, or any power of two
108  *              beginning with 512.
109  *
110  * Return:      Success:        SUCCEED
111  *              Failure:        FAIL
112  *
113  * Programmer:  Robb Matzke
114  *              Friday, November  7, 1997
115  *
116  *-------------------------------------------------------------------------
117  */
118 herr_t
H5FD_locate_signature(H5FD_t * file,const H5P_genplist_t * dxpl,haddr_t * sig_addr)119 H5FD_locate_signature(H5FD_t *file, const H5P_genplist_t *dxpl, haddr_t *sig_addr)
120 {
121     haddr_t         addr, eoa;
122     uint8_t         buf[H5F_SIGNATURE_LEN];
123     unsigned        n, maxpow;
124     herr_t          ret_value = SUCCEED; /* Return value */
125 
126     FUNC_ENTER_NOAPI_NOINIT
127 
128     /* Find the least N such that 2^N is larger than the file size */
129     if(HADDR_UNDEF == (addr = H5FD_get_eof(file)) || HADDR_UNDEF == (eoa = H5FD_get_eoa(file, H5FD_MEM_SUPER)))
130         HGOTO_ERROR(H5E_IO, H5E_CANTINIT, FAIL, "unable to obtain EOF/EOA value")
131     for(maxpow = 0; addr; maxpow++)
132         addr >>= 1;
133     maxpow = MAX(maxpow, 9);
134 
135     /*
136      * Search for the file signature at format address zero followed by
137      * powers of two larger than 9.
138      */
139     for(n = 8; n < maxpow; n++) {
140         addr = (8 == n) ? 0 : (haddr_t)1 << n;
141         if(H5FD_set_eoa(file, H5FD_MEM_SUPER, addr + H5F_SIGNATURE_LEN) < 0)
142             HGOTO_ERROR(H5E_IO, H5E_CANTINIT, FAIL, "unable to set EOA value for file signature")
143         if(H5FD_read(file, dxpl, H5FD_MEM_SUPER, addr, (size_t)H5F_SIGNATURE_LEN, buf) < 0)
144             HGOTO_ERROR(H5E_IO, H5E_CANTINIT, FAIL, "unable to read file signature")
145         if(!HDmemcmp(buf, H5F_SIGNATURE, (size_t)H5F_SIGNATURE_LEN))
146             break;
147     } /* end for */
148 
149     /*
150      * If the signature was not found then reset the EOA value and return
151      * HADDR_UNDEF.
152      */
153     if(n >= maxpow) {
154         if(H5FD_set_eoa(file, H5FD_MEM_SUPER, eoa) < 0)
155             HGOTO_ERROR(H5E_IO, H5E_CANTINIT, FAIL, "unable to reset EOA value")
156         *sig_addr = HADDR_UNDEF;
157     } /* end if */
158     else
159         /* Set return value */
160         *sig_addr = addr;
161 
162 done:
163     FUNC_LEAVE_NOAPI(ret_value)
164 } /* end H5FD_locate_signature() */
165 
166 
167 /*-------------------------------------------------------------------------
168  * Function:	H5FD_read
169  *
170  * Purpose:	Private version of H5FDread()
171  *
172  * Return:	Success:	Non-negative
173  *		Failure:	Negative
174  *
175  * Programmer:	Robb Matzke
176  *              Wednesday, August  4, 1999
177  *
178  *-------------------------------------------------------------------------
179  */
180 herr_t
H5FD_read(H5FD_t * file,const H5P_genplist_t * dxpl,H5FD_mem_t type,haddr_t addr,size_t size,void * buf)181 H5FD_read(H5FD_t *file, const H5P_genplist_t *dxpl, H5FD_mem_t type, haddr_t addr,
182     size_t size, void *buf/*out*/)
183 {
184     haddr_t     eoa = HADDR_UNDEF;
185     herr_t      ret_value = SUCCEED;       /* Return value */
186 
187     FUNC_ENTER_NOAPI(FAIL)
188 
189     HDassert(file && file->cls);
190     HDassert(TRUE == H5P_class_isa(H5P_CLASS(dxpl), H5P_CLS_DATASET_XFER_g));
191     HDassert(buf);
192 
193 #ifndef H5_HAVE_PARALLEL
194     /* Do not return early for Parallel mode since the I/O could be a */
195     /* collective transfer. */
196     /* The no-op case */
197     if(0 == size)
198         HGOTO_DONE(SUCCEED)
199 #endif /* H5_HAVE_PARALLEL */
200 
201     if(HADDR_UNDEF == (eoa = (file->cls->get_eoa)(file, type)))
202 	HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "driver get_eoa request failed")
203     if((addr + file->base_addr + size) > eoa)
204         HGOTO_ERROR(H5E_ARGS, H5E_OVERFLOW, FAIL, "addr overflow, addr = %llu, size=%llu, eoa=%llu",
205                     (unsigned long long)(addr+ file->base_addr), (unsigned long long)size, (unsigned long long)eoa)
206 
207     /* Dispatch to driver */
208     if((file->cls->read)(file, type, H5P_PLIST_ID(dxpl), addr + file->base_addr, size, buf) < 0)
209         HGOTO_ERROR(H5E_VFL, H5E_READERROR, FAIL, "driver read request failed")
210 
211 done:
212     FUNC_LEAVE_NOAPI(ret_value)
213 } /* end H5FD_read() */
214 
215 
216 /*-------------------------------------------------------------------------
217  * Function:	H5FD_write
218  *
219  * Purpose:	Private version of H5FDwrite()
220  *
221  * Return:	Success:	Non-negative
222  *		Failure:	Negative
223  *
224  * Programmer:	Robb Matzke
225  *              Wednesday, August  4, 1999
226  *
227  *-------------------------------------------------------------------------
228  */
229 herr_t
H5FD_write(H5FD_t * file,const H5P_genplist_t * dxpl,H5FD_mem_t type,haddr_t addr,size_t size,const void * buf)230 H5FD_write(H5FD_t *file, const H5P_genplist_t *dxpl, H5FD_mem_t type, haddr_t addr,
231     size_t size, const void *buf)
232 {
233     haddr_t     eoa = HADDR_UNDEF;
234     herr_t      ret_value = SUCCEED;       /* Return value */
235 
236     FUNC_ENTER_NOAPI(FAIL)
237 
238     HDassert(file && file->cls);
239     HDassert(TRUE == H5P_class_isa(H5P_CLASS(dxpl), H5P_CLS_DATASET_XFER_g));
240     HDassert(buf);
241 
242 #ifndef H5_HAVE_PARALLEL
243     /* Do not return early for Parallel mode since the I/O could be a */
244     /* collective transfer. */
245     /* The no-op case */
246     if(0 == size)
247         HGOTO_DONE(SUCCEED)
248 #endif /* H5_HAVE_PARALLEL */
249 
250     if(HADDR_UNDEF == (eoa = (file->cls->get_eoa)(file, type)))
251 	HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "driver get_eoa request failed")
252     if((addr + file->base_addr + size) > eoa)
253         HGOTO_ERROR(H5E_ARGS, H5E_OVERFLOW, FAIL, "addr overflow, addr = %llu, size=%llu, eoa=%llu",
254                     (unsigned long long)(addr+ file->base_addr), (unsigned long long)size, (unsigned long long)eoa)
255 
256     /* Dispatch to driver */
257     if((file->cls->write)(file, type, H5P_PLIST_ID(dxpl), addr + file->base_addr, size, buf) < 0)
258         HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, FAIL, "driver write request failed")
259 
260 done:
261     FUNC_LEAVE_NOAPI(ret_value)
262 } /* end H5FD_write() */
263 
264 
265 /*-------------------------------------------------------------------------
266  * Function:	H5FD_set_eoa
267  *
268  * Purpose:	Private version of H5FDset_eoa()
269  *
270  *              This function expects the EOA is a RELATIVE address, i.e.
271  *              relative to the base address.  This is NOT the same as the
272  *              EOA stored in the superblock, which is an absolute
273  *              address.  Object addresses are relative.
274  *
275  * Return:	Success:	Non-negative
276  *		Failure:	Negative, no side effect
277  *
278  * Programmer:	Robb Matzke
279  *              Wednesday, August  4, 1999
280  *
281  *-------------------------------------------------------------------------
282  */
283 herr_t
H5FD_set_eoa(H5FD_t * file,H5FD_mem_t type,haddr_t addr)284 H5FD_set_eoa(H5FD_t *file, H5FD_mem_t type, haddr_t addr)
285 {
286     herr_t      ret_value = SUCCEED;    /* Return value */
287 
288     FUNC_ENTER_NOAPI(FAIL)
289 
290     HDassert(file && file->cls);
291     HDassert(H5F_addr_defined(addr) && addr <= file->maxaddr);
292 
293     /* Dispatch to driver, convert to absolute address */
294     if((file->cls->set_eoa)(file, type, addr + file->base_addr) < 0)
295 	HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "driver set_eoa request failed")
296 
297 done:
298     FUNC_LEAVE_NOAPI(ret_value)
299 } /* end H5FD_set_eoa() */
300 
301 
302 /*-------------------------------------------------------------------------
303  * Function:	H5FD_get_eoa
304  *
305  * Purpose:	Private version of H5FDget_eoa()
306  *
307  *              This function returns the EOA as a RELATIVE address, i.e.
308  *              relative to the base address.  This is NOT the same as the
309  *              EOA stored in the superblock, which is an absolute
310  *              address.  Object addresses are relative.
311  *
312  * Return:	Success:	First byte after allocated memory.
313  *		Failure:	HADDR_UNDEF
314  *
315  * Programmer:	Robb Matzke
316  *              Wednesday, August  4, 1999
317  *
318  *-------------------------------------------------------------------------
319  */
320 haddr_t
H5FD_get_eoa(const H5FD_t * file,H5FD_mem_t type)321 H5FD_get_eoa(const H5FD_t *file, H5FD_mem_t type)
322 {
323     haddr_t	ret_value;
324 
325     FUNC_ENTER_NOAPI(HADDR_UNDEF)
326 
327     HDassert(file && file->cls);
328 
329     /* Dispatch to driver */
330     if(HADDR_UNDEF == (ret_value = (file->cls->get_eoa)(file, type)))
331 	HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, HADDR_UNDEF, "driver get_eoa request failed")
332 
333     /* Adjust for base address in file (convert to relative address) */
334     ret_value -= file->base_addr;
335 
336 done:
337     FUNC_LEAVE_NOAPI(ret_value)
338 } /* end H5FD_get_eoa() */
339 
340 
341 /*-------------------------------------------------------------------------
342  * Function:	H5FD_get_eof
343  *
344  * Purpose:	Private version of H5FDget_eof()
345  *
346  *              This function returns the EOF as a RELATIVE address, i.e.
347  *              relative to the base address.  This will be different
348  *              from  the end of the physical file if there is a user
349  *              block.
350  *
351  * Return:	Success:	The EOF address.
352  *
353  *		Failure:	HADDR_UNDEF
354  *
355  * Programmer:	Robb Matzke
356  *              Wednesday, August  4, 1999
357  *
358  * Modifications:
359  *
360  *-------------------------------------------------------------------------
361  */
362 haddr_t
H5FD_get_eof(const H5FD_t * file)363 H5FD_get_eof(const H5FD_t *file)
364 {
365     haddr_t	ret_value;
366 
367     FUNC_ENTER_NOAPI(HADDR_UNDEF)
368 
369     HDassert(file && file->cls);
370 
371     /* Dispatch to driver */
372     if(file->cls->get_eof) {
373 	if(HADDR_UNDEF == (ret_value = (file->cls->get_eof)(file)))
374 	    HGOTO_ERROR(H5E_VFL, H5E_CANTGET, HADDR_UNDEF, "driver get_eof request failed")
375     } /* end if */
376     else
377 	ret_value = file->maxaddr;
378 
379     /* Adjust for base address in file (convert to relative address)  */
380     ret_value -= file->base_addr;
381 
382 done:
383     FUNC_LEAVE_NOAPI(ret_value)
384 } /* end H5FD_get_eof() */
385 
386