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