1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2  * Copyright by The HDF Group.                                               *
3  * All rights reserved.                                                      *
4  *                                                                           *
5  * This file is part of HDF5.  The full HDF5 copyright notice, including     *
6  * terms governing use, modification, and redistribution, is contained in    *
7  * the COPYING file, which can be found at the root of the source code       *
8  * distribution tree, or in https://www.hdfgroup.org/licenses.               *
9  * If you do not have access to either file, you may request a copy from     *
10  * help@hdfgroup.org.                                                        *
11  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
12 
13 /*
14  * Purpose:     Link callbacks for the native VOL connector
15  *
16  */
17 
18 #define H5L_FRIEND /* Suppress error about including H5Lpkg    */
19 
20 #include "H5private.h"   /* Generic Functions                        */
21 #include "H5Eprivate.h"  /* Error handling                           */
22 #include "H5Gprivate.h"  /* Groups                                   */
23 #include "H5Iprivate.h"  /* IDs                                      */
24 #include "H5Lpkg.h"      /* Links                                    */
25 #include "H5Pprivate.h"  /* Property lists                           */
26 #include "H5VLprivate.h" /* Virtual Object Layer                     */
27 
28 #include "H5VLnative_private.h" /* Native VOL connector                     */
29 
30 /*-------------------------------------------------------------------------
31  * Function:    H5VL__native_link_create
32  *
33  * Purpose:     Handles the link create callback
34  *
35  * Return:      SUCCEED/FAIL
36  *
37  *-------------------------------------------------------------------------
38  */
39 herr_t
H5VL__native_link_create(H5VL_link_create_type_t create_type,void * obj,const H5VL_loc_params_t * loc_params,hid_t lcpl_id,hid_t H5_ATTR_UNUSED lapl_id,hid_t H5_ATTR_UNUSED dxpl_id,void H5_ATTR_UNUSED ** req,va_list arguments)40 H5VL__native_link_create(H5VL_link_create_type_t create_type, void *obj, const H5VL_loc_params_t *loc_params,
41                          hid_t lcpl_id, hid_t H5_ATTR_UNUSED lapl_id, hid_t H5_ATTR_UNUSED dxpl_id,
42                          void H5_ATTR_UNUSED **req, va_list arguments)
43 {
44     herr_t ret_value = SUCCEED; /* Return value */
45 
46     FUNC_ENTER_PACKAGE
47 
48     switch (create_type) {
49         case H5VL_LINK_CREATE_HARD: {
50             H5G_loc_t          cur_loc;
51             H5G_loc_t          link_loc;
52             void *             cur_obj    = HDva_arg(arguments, void *);
53             H5VL_loc_params_t *cur_params = HDva_arg(arguments, H5VL_loc_params_t *);
54 
55             if (NULL != cur_obj && H5G_loc_real(cur_obj, cur_params->obj_type, &cur_loc) < 0)
56                 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file or file object")
57             if (NULL != obj && H5G_loc_real(obj, loc_params->obj_type, &link_loc) < 0)
58                 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file or file object")
59 
60             /* H5Lcreate_hard */
61             if (H5VL_OBJECT_BY_NAME == cur_params->type) {
62                 H5G_loc_t *cur_loc_p, *link_loc_p;
63 
64                 /* Set up current & new location pointers */
65                 cur_loc_p  = &cur_loc;
66                 link_loc_p = &link_loc;
67                 if (NULL == cur_obj)
68                     cur_loc_p = link_loc_p;
69                 else if (NULL == obj)
70                     link_loc_p = cur_loc_p;
71                 else if (cur_loc_p->oloc->file != link_loc_p->oloc->file)
72                     HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
73                                 "source and destination should be in the same file.")
74 
75                 /* Create the link */
76                 if ((ret_value =
77                          H5L__create_hard(cur_loc_p, cur_params->loc_data.loc_by_name.name, link_loc_p,
78                                           loc_params->loc_data.loc_by_name.name, lcpl_id)) < 0)
79                     HGOTO_ERROR(H5E_LINK, H5E_CANTINIT, FAIL, "unable to create link")
80             }      /* end if */
81             else { /* H5Olink */
82                 /* Link to the object */
83                 if (H5L_link(&link_loc, loc_params->loc_data.loc_by_name.name, &cur_loc, lcpl_id) < 0)
84                     HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to create link")
85             } /* end else */
86             break;
87         }
88 
89         case H5VL_LINK_CREATE_SOFT: {
90             char *    target_name = HDva_arg(arguments, char *);
91             H5G_loc_t link_loc; /* Group location for new link */
92 
93             if (H5G_loc_real(obj, loc_params->obj_type, &link_loc) < 0)
94                 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file or file object")
95 
96             /* Create the link */
97             if ((ret_value = H5L__create_soft(target_name, &link_loc, loc_params->loc_data.loc_by_name.name,
98                                               lcpl_id)) < 0)
99                 HGOTO_ERROR(H5E_LINK, H5E_CANTINIT, FAIL, "unable to create link")
100             break;
101         }
102 
103         case H5VL_LINK_CREATE_UD: {
104             H5G_loc_t  link_loc; /* Group location for new link */
105             H5L_type_t link_type  = (H5L_type_t)HDva_arg(arguments, int);
106             void *     udata      = HDva_arg(arguments, void *);
107             size_t     udata_size = HDva_arg(arguments, size_t);
108 
109             if (H5G_loc_real(obj, loc_params->obj_type, &link_loc) < 0)
110                 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file or file object")
111 
112             /* Create link */
113             if (H5L__create_ud(&link_loc, loc_params->loc_data.loc_by_name.name, udata, udata_size, link_type,
114                                lcpl_id) < 0)
115                 HGOTO_ERROR(H5E_LINK, H5E_CANTINIT, FAIL, "unable to create link")
116             break;
117         }
118 
119         default:
120             HGOTO_ERROR(H5E_LINK, H5E_CANTINIT, FAIL, "invalid link creation call")
121     } /* end switch */
122 
123 done:
124     FUNC_LEAVE_NOAPI(ret_value)
125 } /* end H5VL__native_link_create() */
126 
127 /*-------------------------------------------------------------------------
128  * Function:    H5VL__native_link_copy
129  *
130  * Purpose:     Handles the link copy callback
131  *
132  * Return:      SUCCEED/FAIL
133  *
134  *-------------------------------------------------------------------------
135  */
136 herr_t
H5VL__native_link_copy(void * src_obj,const H5VL_loc_params_t * loc_params1,void * dst_obj,const H5VL_loc_params_t * loc_params2,hid_t lcpl_id,hid_t H5_ATTR_UNUSED lapl_id,hid_t H5_ATTR_UNUSED dxpl_id,void H5_ATTR_UNUSED ** req)137 H5VL__native_link_copy(void *src_obj, const H5VL_loc_params_t *loc_params1, void *dst_obj,
138                        const H5VL_loc_params_t *loc_params2, hid_t lcpl_id, hid_t H5_ATTR_UNUSED lapl_id,
139                        hid_t H5_ATTR_UNUSED dxpl_id, void H5_ATTR_UNUSED **req)
140 {
141     H5G_loc_t src_loc, *src_loc_p;
142     H5G_loc_t dst_loc, *dst_loc_p;
143     herr_t    ret_value = SUCCEED; /* Return value */
144 
145     FUNC_ENTER_PACKAGE
146 
147     if (NULL != src_obj && H5G_loc_real(src_obj, loc_params1->obj_type, &src_loc) < 0)
148         HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file or file object")
149     if (NULL != dst_obj && H5G_loc_real(dst_obj, loc_params2->obj_type, &dst_loc) < 0)
150         HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file or file object")
151 
152     /* Set up src & dst location pointers */
153     src_loc_p = &src_loc;
154     dst_loc_p = &dst_loc;
155     if (NULL == src_obj)
156         src_loc_p = dst_loc_p;
157     else if (NULL == dst_obj)
158         dst_loc_p = src_loc_p;
159 
160     /* Copy the link */
161     if (H5L__move(src_loc_p, loc_params1->loc_data.loc_by_name.name, dst_loc_p,
162                   loc_params2->loc_data.loc_by_name.name, TRUE, lcpl_id) < 0)
163         HGOTO_ERROR(H5E_LINK, H5E_CANTCOPY, FAIL, "unable to copy link")
164 
165 done:
166     FUNC_LEAVE_NOAPI(ret_value)
167 } /* end H5VL__native_link_copy() */
168 
169 /*-------------------------------------------------------------------------
170  * Function:    H5VL__native_link_move
171  *
172  * Purpose:     Handles the link move callback
173  *
174  * Return:      SUCCEED/FAIL
175  *
176  *-------------------------------------------------------------------------
177  */
178 herr_t
H5VL__native_link_move(void * src_obj,const H5VL_loc_params_t * loc_params1,void * dst_obj,const H5VL_loc_params_t * loc_params2,hid_t lcpl_id,hid_t H5_ATTR_UNUSED lapl_id,hid_t H5_ATTR_UNUSED dxpl_id,void H5_ATTR_UNUSED ** req)179 H5VL__native_link_move(void *src_obj, const H5VL_loc_params_t *loc_params1, void *dst_obj,
180                        const H5VL_loc_params_t *loc_params2, hid_t lcpl_id, hid_t H5_ATTR_UNUSED lapl_id,
181                        hid_t H5_ATTR_UNUSED dxpl_id, void H5_ATTR_UNUSED **req)
182 {
183     H5G_loc_t src_loc, *src_loc_p;
184     H5G_loc_t dst_loc, *dst_loc_p;
185     herr_t    ret_value = SUCCEED; /* Return value */
186 
187     FUNC_ENTER_PACKAGE
188 
189     if (NULL != src_obj && H5G_loc_real(src_obj, loc_params1->obj_type, &src_loc) < 0)
190         HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file or file object")
191     if (NULL != dst_obj && H5G_loc_real(dst_obj, loc_params2->obj_type, &dst_loc) < 0)
192         HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file or file object")
193 
194     /* Set up src & dst location pointers */
195     src_loc_p = &src_loc;
196     dst_loc_p = &dst_loc;
197     if (NULL == src_obj)
198         src_loc_p = dst_loc_p;
199     else if (NULL == dst_obj)
200         dst_loc_p = src_loc_p;
201 
202     /* Move the link */
203     if (H5L__move(src_loc_p, loc_params1->loc_data.loc_by_name.name, dst_loc_p,
204                   loc_params2->loc_data.loc_by_name.name, FALSE, lcpl_id) < 0)
205         HGOTO_ERROR(H5E_LINK, H5E_CANTMOVE, FAIL, "unable to move link")
206 
207 done:
208     FUNC_LEAVE_NOAPI(ret_value)
209 } /* end H5VL__native_link_move() */
210 
211 /*-------------------------------------------------------------------------
212  * Function:    H5VL__native_link_get
213  *
214  * Purpose:     Handles the link get callback
215  *
216  * Return:      SUCCEED/FAIL
217  *
218  *-------------------------------------------------------------------------
219  */
220 herr_t
H5VL__native_link_get(void * obj,const H5VL_loc_params_t * loc_params,H5VL_link_get_t get_type,hid_t H5_ATTR_UNUSED dxpl_id,void H5_ATTR_UNUSED ** req,va_list arguments)221 H5VL__native_link_get(void *obj, const H5VL_loc_params_t *loc_params, H5VL_link_get_t get_type,
222                       hid_t H5_ATTR_UNUSED dxpl_id, void H5_ATTR_UNUSED **req, va_list arguments)
223 {
224     H5G_loc_t loc;
225     herr_t    ret_value = SUCCEED; /* Return value */
226 
227     FUNC_ENTER_PACKAGE
228 
229     if (H5G_loc_real(obj, loc_params->obj_type, &loc) < 0)
230         HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file or file object")
231 
232     switch (get_type) {
233         /* H5Lget_info/H5Lget_info_by_idx */
234         case H5VL_LINK_GET_INFO: {
235             H5L_info2_t *linfo2 = HDva_arg(arguments, H5L_info2_t *);
236 
237             /* Get the link information */
238             if (loc_params->type == H5VL_OBJECT_BY_NAME) { /* H5Lget_info */
239                 if (H5L_get_info(&loc, loc_params->loc_data.loc_by_name.name, linfo2) < 0)
240                     HGOTO_ERROR(H5E_LINK, H5E_NOTFOUND, FAIL, "unable to get link info")
241             }                                                  /* end if */
242             else if (loc_params->type == H5VL_OBJECT_BY_IDX) { /* H5Lget_info_by_idx */
243                 if (H5L__get_info_by_idx(
244                         &loc, loc_params->loc_data.loc_by_idx.name, loc_params->loc_data.loc_by_idx.idx_type,
245                         loc_params->loc_data.loc_by_idx.order, loc_params->loc_data.loc_by_idx.n, linfo2) < 0)
246                     HGOTO_ERROR(H5E_LINK, H5E_NOTFOUND, FAIL, "unable to get link info")
247             } /* end else-if */
248             else
249                 HGOTO_ERROR(H5E_LINK, H5E_NOTFOUND, FAIL, "unable to get link info")
250 
251             break;
252         }
253 
254         /* H5Lget_name_by_idx */
255         case H5VL_LINK_GET_NAME: {
256             char *   name = HDva_arg(arguments, char *);
257             size_t   size = HDva_arg(arguments, size_t);
258             ssize_t *ret  = HDva_arg(arguments, ssize_t *);
259 
260             /* Get the link name */
261             if ((*ret = H5L__get_name_by_idx(&loc, loc_params->loc_data.loc_by_idx.name,
262                                              loc_params->loc_data.loc_by_idx.idx_type,
263                                              loc_params->loc_data.loc_by_idx.order,
264                                              loc_params->loc_data.loc_by_idx.n, name, size)) < 0)
265                 HGOTO_ERROR(H5E_LINK, H5E_NOTFOUND, FAIL, "unable to get link info")
266 
267             break;
268         }
269 
270         /* H5Lget_val/H5Lget_val_by_idx */
271         case H5VL_LINK_GET_VAL: {
272             void * buf  = HDva_arg(arguments, void *);
273             size_t size = HDva_arg(arguments, size_t);
274 
275             /* Get the link information */
276             if (loc_params->type == H5VL_OBJECT_BY_NAME) { /* H5Lget_val */
277                 if (H5L__get_val(&loc, loc_params->loc_data.loc_by_name.name, buf, size) < 0)
278                     HGOTO_ERROR(H5E_LINK, H5E_NOTFOUND, FAIL, "unable to get link value")
279             }
280             else if (loc_params->type == H5VL_OBJECT_BY_IDX) { /* H5Lget_val_by_idx */
281 
282                 if (H5L__get_val_by_idx(&loc, loc_params->loc_data.loc_by_idx.name,
283                                         loc_params->loc_data.loc_by_idx.idx_type,
284                                         loc_params->loc_data.loc_by_idx.order,
285                                         loc_params->loc_data.loc_by_idx.n, buf, size) < 0)
286                     HGOTO_ERROR(H5E_LINK, H5E_NOTFOUND, FAIL, "unable to get link val")
287             }
288             else
289                 HGOTO_ERROR(H5E_LINK, H5E_NOTFOUND, FAIL, "unable to get link val")
290 
291             break;
292         }
293 
294         default:
295             HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "can't get this type of information from link")
296     } /* end switch */
297 
298 done:
299     FUNC_LEAVE_NOAPI(ret_value)
300 } /* end H5VL__native_link_get() */
301 
302 /*-------------------------------------------------------------------------
303  * Function:    H5VL__native_link_specific
304  *
305  * Purpose:     Handles the link specific callback
306  *
307  * Return:      SUCCEED/FAIL
308  *
309  *-------------------------------------------------------------------------
310  */
311 herr_t
H5VL__native_link_specific(void * obj,const H5VL_loc_params_t * loc_params,H5VL_link_specific_t specific_type,hid_t H5_ATTR_UNUSED dxpl_id,void H5_ATTR_UNUSED ** req,va_list arguments)312 H5VL__native_link_specific(void *obj, const H5VL_loc_params_t *loc_params, H5VL_link_specific_t specific_type,
313                            hid_t H5_ATTR_UNUSED dxpl_id, void H5_ATTR_UNUSED **req, va_list arguments)
314 {
315     herr_t ret_value = SUCCEED; /* Return value */
316 
317     FUNC_ENTER_PACKAGE
318 
319     switch (specific_type) {
320         case H5VL_LINK_EXISTS: {
321             htri_t *  ret = HDva_arg(arguments, htri_t *);
322             H5G_loc_t loc;
323 
324             if (H5G_loc_real(obj, loc_params->obj_type, &loc) < 0)
325                 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file or file object")
326 
327             /* Check for the existence of the link */
328             if ((*ret = H5L__exists(&loc, loc_params->loc_data.loc_by_name.name)) < 0)
329                 HGOTO_ERROR(H5E_LINK, H5E_NOTFOUND, FAIL, "unable to specific link info")
330             break;
331         }
332 
333         case H5VL_LINK_ITER: {
334             H5G_loc_t       loc;
335             hbool_t         recursive = (hbool_t)HDva_arg(arguments, unsigned);
336             H5_index_t      idx_type  = (H5_index_t)HDva_arg(arguments, int);      /* enum work-around */
337             H5_iter_order_t order     = (H5_iter_order_t)HDva_arg(arguments, int); /* enum work-around */
338             hsize_t *       idx_p     = HDva_arg(arguments, hsize_t *);
339             H5L_iterate2_t  op        = HDva_arg(arguments, H5L_iterate2_t);
340             void *          op_data   = HDva_arg(arguments, void *);
341 
342             /* Get the location */
343             if (H5G_loc_real(obj, loc_params->obj_type, &loc) < 0)
344                 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
345 
346             /* Visit or iterate over the links */
347             if (loc_params->type == H5VL_OBJECT_BY_SELF) {
348                 if (recursive) {
349                     /* H5Lvisit */
350                     if ((ret_value = H5G_visit(&loc, ".", idx_type, order, op, op_data)) < 0)
351                         HGOTO_ERROR(H5E_LINK, H5E_BADITER, FAIL, "link visitation failed")
352                 } /* end if */
353                 else {
354                     /* H5Literate */
355                     if ((ret_value = H5L_iterate(&loc, ".", idx_type, order, idx_p, op, op_data)) < 0)
356                         HGOTO_ERROR(H5E_LINK, H5E_BADITER, FAIL, "error iterating over links")
357                 } /* end else */
358             }     /* end if */
359             else if (loc_params->type == H5VL_OBJECT_BY_NAME) {
360                 if (recursive) {
361                     /* H5Lvisit_by_name */
362                     if ((ret_value = H5G_visit(&loc, loc_params->loc_data.loc_by_name.name, idx_type, order,
363                                                op, op_data)) < 0)
364                         HGOTO_ERROR(H5E_LINK, H5E_BADITER, FAIL, "link visitation failed")
365                 } /* end if */
366                 else {
367                     /* H5Literate_by_name */
368                     if ((ret_value = H5L_iterate(&loc, loc_params->loc_data.loc_by_name.name, idx_type, order,
369                                                  idx_p, op, op_data)) < 0)
370                         HGOTO_ERROR(H5E_LINK, H5E_BADITER, FAIL, "error iterating over links")
371                 } /* end else */
372             }     /* end else-if */
373             else
374                 HGOTO_ERROR(H5E_LINK, H5E_UNSUPPORTED, FAIL, "unknown link iterate params")
375 
376             break;
377         }
378 
379         case H5VL_LINK_DELETE: {
380             H5G_loc_t loc;
381 
382             if (H5G_loc_real(obj, loc_params->obj_type, &loc) < 0)
383                 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file or file object")
384 
385             /* Unlink */
386             if (loc_params->type == H5VL_OBJECT_BY_NAME) { /* H5Ldelete */
387                 if (H5L__delete(&loc, loc_params->loc_data.loc_by_name.name) < 0)
388                     HGOTO_ERROR(H5E_LINK, H5E_CANTDELETE, FAIL, "unable to delete link")
389             }                                                  /* end if */
390             else if (loc_params->type == H5VL_OBJECT_BY_IDX) { /* H5Ldelete_by_idx */
391                 if (H5L__delete_by_idx(
392                         &loc, loc_params->loc_data.loc_by_idx.name, loc_params->loc_data.loc_by_idx.idx_type,
393                         loc_params->loc_data.loc_by_idx.order, loc_params->loc_data.loc_by_idx.n) < 0)
394                     HGOTO_ERROR(H5E_LINK, H5E_CANTDELETE, FAIL, "unable to delete link")
395             } /* end else-if */
396             else
397                 HGOTO_ERROR(H5E_LINK, H5E_CANTDELETE, FAIL, "unable to delete link")
398             break;
399         }
400 
401         default:
402             HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "invalid specific operation")
403     } /* end switch */
404 
405 done:
406     FUNC_LEAVE_NOAPI(ret_value)
407 } /* end H5VL__native_link_specific() */
408