|
1 | | -# Path Resolution for JLD2 External Links |
2 | | -# This module provides secure path resolution functionality for external file links |
3 | | - |
4 | | -""" |
5 | | - resolve_external_file_path(current_file_path::String, external_file_path::String) -> String |
6 | | -
|
7 | | -Resolve an external file path relative to the current file's directory. |
8 | | -
|
9 | | -# Arguments |
10 | | -- `current_file_path`: Path to the current JLD2 file (used as reference for relative paths) |
11 | | -- `external_file_path`: The external file path from the external link (may be relative or absolute) |
12 | | -
|
13 | | -# Returns |
14 | | -The resolved absolute path to the external file. |
15 | | -
|
16 | | -# Path Processing |
17 | | -- Normalizes path separators for cross-platform compatibility |
18 | | -- Resolves relative paths relative to the current file's directory |
19 | | -
|
20 | | -# Examples |
21 | | -```julia |
22 | | -# Relative external file path |
23 | | -current = "/home/user/data/main.jld2" |
24 | | -external = "./external_data.jld2" |
25 | | -resolved = resolve_external_file_path(current, external) |
26 | | -# Result: "/home/user/data/external_data.jld2" |
27 | | -
|
28 | | -# Absolute external file path |
29 | | -current = "/home/user/data/main.jld2" |
30 | | -external = "/shared/datasets/public.jld2" |
31 | | -resolved = resolve_external_file_path(current, external) |
32 | | -# Result: "/shared/datasets/public.jld2" |
33 | | -``` |
34 | | -""" |
35 | 1 | function resolve_external_file_path(current_file_path::String, external_file_path::String) |
36 | | - # Handle absolute paths directly |
37 | | - if isabspath(external_file_path) |
38 | | - resolved_path = abspath(external_file_path) |
39 | | - else |
40 | | - # Resolve relative to current file's directory |
41 | | - current_dir = dirname(current_file_path) |
42 | | - resolved_path = abspath(joinpath(current_dir, external_file_path)) |
43 | | - end |
44 | | - |
45 | | - return resolved_path |
46 | | -end |
47 | | - |
48 | | - |
49 | | -""" |
50 | | - resolve_soft_link_path(group_path::String, soft_link_path::String) -> String |
51 | | -
|
52 | | -Resolve a soft link path within the same HDF5 file. |
53 | | -
|
54 | | -# Arguments |
55 | | -- `group_path`: Current group's absolute path within the HDF5 file (e.g., "/data/measurements") |
56 | | -- `soft_link_path`: The soft link target path (may be absolute or relative) |
57 | | -
|
58 | | -# Returns |
59 | | -The resolved absolute path within the HDF5 file. |
60 | | -
|
61 | | -# Path Resolution Rules |
62 | | -- Absolute paths (starting with '/') are used as-is |
63 | | -- Relative paths are resolved relative to the containing group |
64 | | -- Path separators are normalized to '/' for HDF5 compatibility |
65 | | -- ".." components navigate up the group hierarchy |
66 | | -
|
67 | | -# Examples |
68 | | -```julia |
69 | | -# Absolute soft link |
70 | | -group_path = "/data/measurements" |
71 | | -soft_path = "/results/analysis" |
72 | | -resolved = resolve_soft_link_path(group_path, soft_path) |
73 | | -# Result: "/results/analysis" |
74 | | -
|
75 | | -# Relative soft link |
76 | | -group_path = "/data/measurements" |
77 | | -soft_path = "../calibration/offset" |
78 | | -resolved = resolve_soft_link_path(group_path, soft_path) |
79 | | -# Result: "/data/calibration/offset" |
80 | | -``` |
81 | | -""" |
82 | | -function resolve_soft_link_path(group_path::String, soft_link_path::String) |
83 | | - # Normalize path separators to HDF5 standard |
84 | | - normalized_soft_path = replace(soft_link_path, '\\' => '/') |
85 | | - normalized_group_path = replace(group_path, '\\' => '/') |
86 | | - |
87 | | - # Handle absolute paths |
88 | | - if startswith(normalized_soft_path, '/') |
89 | | - return normalize_hdf5_path(normalized_soft_path) |
90 | | - end |
91 | | - |
92 | | - # Handle relative paths |
93 | | - # Start from the group itself (not the parent directory) |
94 | | - base_path = normalized_group_path |
95 | | - |
96 | | - # Handle empty base path (root group case) |
97 | | - if isempty(base_path) || base_path == "." |
98 | | - base_path = "/" |
99 | | - end |
100 | | - |
101 | | - # Resolve relative path components |
102 | | - path_components = split(normalized_soft_path, '/') |
103 | | - current_components = split(base_path, '/', keepempty=false) |
104 | | - |
105 | | - for component in path_components |
106 | | - if component == ".." && !isempty(current_components) |
107 | | - pop!(current_components) # Go up one level |
108 | | - elseif component != "." && !isempty(component) |
109 | | - push!(current_components, component) # Add component |
110 | | - end |
111 | | - # Ignore "." and empty components |
112 | | - end |
113 | | - |
114 | | - # Reconstruct path |
115 | | - if isempty(current_components) |
116 | | - return "/" |
117 | | - else |
118 | | - return "/" * join(current_components, "/") |
119 | | - end |
| 2 | + current_dir = dirname(current_file_path) |
| 3 | + return abspath(joinpath(current_dir, external_file_path)) |
120 | 4 | end |
121 | 5 |
|
122 | | -""" |
123 | | - normalize_hdf5_path(path::String) -> String |
124 | | -
|
125 | | -Normalize an HDF5 path to standard format. |
126 | | -
|
127 | | -# Rules |
128 | | -- Ensures path starts with '/' (absolute) |
129 | | -- Normalizes path separators to '/' |
130 | | -- Removes redundant components like "//" or "/./" |
131 | | -- Handles ".." components properly |
132 | | -
|
133 | | -# Examples |
134 | | -```julia |
135 | | -normalize_hdf5_path("/data//measurements/./temp") # => "/data/measurements/temp" |
136 | | -normalize_hdf5_path("data/measurements") # => "/data/measurements" |
137 | | -``` |
138 | | -""" |
139 | | -function normalize_hdf5_path(path::String) |
140 | | - # Normalize separators |
141 | | - normalized = replace(path, '\\' => '/') |
142 | | - |
143 | | - # Ensure absolute path |
144 | | - if !startswith(normalized, '/') |
145 | | - normalized = "/" * normalized |
146 | | - end |
147 | | - |
148 | | - # Split, process, and rejoin components |
149 | | - components = split(normalized, '/', keepempty=false) |
150 | | - result_components = String[] |
151 | | - |
152 | | - for component in components |
153 | | - if component == ".." |
154 | | - # Go up one level (remove last component if any) |
155 | | - if !isempty(result_components) |
156 | | - pop!(result_components) |
157 | | - end |
158 | | - elseif component != "." && !isempty(component) |
159 | | - # Add non-empty, non-current-directory components |
160 | | - push!(result_components, component) |
161 | | - end |
162 | | - # Ignore "." and empty components |
163 | | - end |
164 | | - |
165 | | - # Reconstruct path |
166 | | - if isempty(result_components) |
167 | | - return "/" |
168 | | - else |
169 | | - return "/" * join(result_components, "/") |
| 6 | +function resolve_soft_link(g::Group, path::String) |
| 7 | + if !startswith(path, '/') |
| 8 | + path = group_path(g) * "/" * path |
170 | 9 | end |
| 10 | + return path |
171 | 11 | end |
172 | | - |
0 commit comments