@@ -7,8 +7,8 @@ use hdf5_sys::{
7
7
h5d:: H5Dopen2 ,
8
8
h5g:: { H5G_info_t , H5Gcreate2 , H5Gget_info , H5Gopen2 } ,
9
9
h5l:: {
10
- H5L_info_t , H5L_iterate_t , H5Lcreate_hard , H5Lcreate_soft , H5Ldelete , H5Lexists ,
11
- H5Literate , H5Lmove , H5L_SAME_LOC ,
10
+ H5L_info_t , H5L_iterate_t , H5Lcreate_external , H5Lcreate_hard , H5Lcreate_soft , H5Ldelete ,
11
+ H5Lexists , H5Literate , H5Lmove , H5L_SAME_LOC ,
12
12
} ,
13
13
h5p:: { H5Pcreate , H5Pset_create_intermediate_group } ,
14
14
} ;
@@ -102,34 +102,69 @@ impl Group {
102
102
Self :: from_id ( h5try ! ( H5Gopen2 ( self . id( ) , name. as_ptr( ) , H5P_DEFAULT ) ) )
103
103
}
104
104
105
- /// Creates a soft link. Note: `src` and `dst` are relative to the current object.
106
- pub fn link_soft ( & self , src : & str , dst : & str ) -> Result < ( ) > {
105
+ /// Creates a soft link.
106
+ ///
107
+ /// A soft link does not require the linked object to exist.
108
+ /// Note: `target` and `link_name` are relative to the current object.
109
+ pub fn link_soft ( & self , target : & str , link_name : & str ) -> Result < ( ) > {
107
110
// TODO: &mut self?
108
111
h5lock ! ( {
109
112
let lcpl = make_lcpl( ) ?;
110
- let src = to_cstring( src) ?;
111
- let dst = to_cstring( dst) ?;
112
- h5call!( H5Lcreate_soft ( src. as_ptr( ) , self . id( ) , dst. as_ptr( ) , lcpl. id( ) , H5P_DEFAULT ) )
113
- . and( Ok ( ( ) ) )
113
+ let target = to_cstring( target) ?;
114
+ let link_name = to_cstring( link_name) ?;
115
+ h5call!( H5Lcreate_soft (
116
+ target. as_ptr( ) ,
117
+ self . id( ) ,
118
+ link_name. as_ptr( ) ,
119
+ lcpl. id( ) ,
120
+ H5P_DEFAULT
121
+ ) )
122
+ . and( Ok ( ( ) ) )
114
123
} )
115
124
}
116
125
117
- /// Creates a hard link. Note: `src ` and `dst ` are relative to the current object.
118
- pub fn link_hard ( & self , src : & str , dst : & str ) -> Result < ( ) > {
126
+ /// Creates a hard link. Note: `target ` and `link_name ` are relative to the current object.
127
+ pub fn link_hard ( & self , target : & str , link_name : & str ) -> Result < ( ) > {
119
128
// TODO: &mut self?
120
- let src = to_cstring ( src ) ?;
121
- let dst = to_cstring ( dst ) ?;
129
+ let target = to_cstring ( target ) ?;
130
+ let link_name = to_cstring ( link_name ) ?;
122
131
h5call ! ( H5Lcreate_hard (
123
132
self . id( ) ,
124
- src . as_ptr( ) ,
133
+ target . as_ptr( ) ,
125
134
H5L_SAME_LOC ,
126
- dst . as_ptr( ) ,
135
+ link_name . as_ptr( ) ,
127
136
H5P_DEFAULT ,
128
137
H5P_DEFAULT
129
138
) )
130
139
. and ( Ok ( ( ) ) )
131
140
}
132
141
142
+ /// Creates an external link.
143
+ ///
144
+ /// Note: `link_name` is relative to the current object,
145
+ /// `target` is relative to the root of the source file,
146
+ /// `target_file_name` is the path to the external file.
147
+ ///
148
+ /// For a detailed explanation on how `target_file_name` is resolved, see
149
+ /// [https://portal.hdfgroup.org/display/HDF5/H5L_CREATE_EXTERNAL](https://portal.hdfgroup.org/display/HDF5/H5L_CREATE_EXTERNAL)
150
+ pub fn link_external (
151
+ & self , target_file_name : & str , target : & str , link_name : & str ,
152
+ ) -> Result < ( ) > {
153
+ // TODO: &mut self?
154
+ let target = to_cstring ( target) ?;
155
+ let target_file_name = to_cstring ( target_file_name) ?;
156
+ let link_name = to_cstring ( link_name) ?;
157
+ h5call ! ( H5Lcreate_external (
158
+ target_file_name. as_ptr( ) ,
159
+ target. as_ptr( ) ,
160
+ self . id( ) ,
161
+ link_name. as_ptr( ) ,
162
+ H5P_DEFAULT ,
163
+ H5P_DEFAULT ,
164
+ ) )
165
+ . and ( Ok ( ( ) ) )
166
+ }
167
+
133
168
/// Relinks an object. Note: `name` and `path` are relative to the current object.
134
169
pub fn relink ( & self , name : & str , path : & str ) -> Result < ( ) > {
135
170
// TODO: &mut self?
@@ -412,4 +447,28 @@ pub mod tests {
412
447
assert_eq ! ( file. member_names( ) . unwrap( ) , vec![ "a" , "b" ] ) ;
413
448
} )
414
449
}
450
+
451
+ #[ test]
452
+ pub fn test_external_link ( ) {
453
+ with_tmp_dir ( |dir| {
454
+ let file1 = dir. join ( "foo.h5" ) ;
455
+ let file1 = File :: create ( file1) . unwrap ( ) ;
456
+ let dset1 = file1. new_dataset :: < i32 > ( ) . create ( "foo" ) . unwrap ( ) ;
457
+ dset1. write_scalar ( & 13 ) . unwrap ( ) ;
458
+
459
+ let file2 = dir. join ( "bar.h5" ) ;
460
+ let file2 = File :: create ( file2) . unwrap ( ) ;
461
+ file2. link_external ( "foo.h5" , "foo" , "bar" ) . unwrap ( ) ;
462
+ let dset2 = file2. dataset ( "bar" ) . unwrap ( ) ;
463
+ assert_eq ! ( dset2. read_scalar:: <i32 >( ) . unwrap( ) , 13 ) ;
464
+
465
+ file1. unlink ( "foo" ) . unwrap ( ) ;
466
+ assert ! ( file1. dataset( "foo" ) . is_err( ) ) ;
467
+ assert ! ( file2. dataset( "bar" ) . is_err( ) ) ;
468
+
469
+ // foo is only weakly closed
470
+ assert_eq ! ( dset1. read_scalar:: <i32 >( ) . unwrap( ) , 13 ) ;
471
+ assert_eq ! ( dset2. read_scalar:: <i32 >( ) . unwrap( ) , 13 ) ;
472
+ } )
473
+ }
415
474
}
0 commit comments