MCPcopy Create free account
hub / github.com/containerd/nerdctl / getPathSpecFromContainer

Function getPathSpecFromContainer

pkg/containerutil/cp_resolve_linux.go:139–222  ·  view source on GitHub ↗

getPathSpecFromContainer builds a pathSpecifier from a container location

(originalPath string, conSpec *oci.Spec, containerHostRoot string)

Source from the content-addressed store, hash-verified

137
138// getPathSpecFromContainer builds a pathSpecifier from a container location
139func getPathSpecFromContainer(originalPath string, conSpec *oci.Spec, containerHostRoot string) (*pathSpecifier, error) {
140 pathSpec := &pathSpecifier{
141 originalPath: originalPath,
142 endsWithSeparator: strings.HasSuffix(originalPath, string(os.PathSeparator)),
143 endsWithSeparatorDot: filepath.Base(originalPath) == ".",
144 }
145
146 path := originalPath
147
148 // Path may still be relative at this point. If it is, join it to the root
149 // NOTE: this is specifically called out in the docker reference. Paths in the container are assumed
150 // relative to the root, and not to the current (container) working directory.
151 // Though this seems like a questionable decision, it is set.
152 if !filepath.IsAbs(path) {
153 path = string(os.PathSeparator) + path
154 }
155
156 // Now, fully resolve the path - resolving all symlinks and cleaning-up the end result, following across mounts
157 pathResolver := newResolver(conSpec, containerHostRoot)
158 resolvedContainerPath, err := pathResolver.resolvePath(path)
159
160 // Errors we get from that are from Lstat or Readlink
161 // Either the object does not exist, or we have a dangling symlink, or otherwise hosed filesystem entries
162 if err != nil && !errors.Is(err, os.ErrNotExist) {
163 if errors.Is(err, syscall.ENOTDIR) {
164 return nil, errors.Join(errIsNotADir, err)
165 }
166
167 // errors.New("EvalSymlinks: too many links")
168 // other errors would come from lstat
169 return nil, err
170 }
171
172 pathSpec.exists = err == nil
173
174 // If the resource does not exist
175 if !pathSpec.exists {
176 // Try the parent
177 cleaned := strings.TrimRight(strings.TrimSuffix(path, string(os.PathSeparator)+"."), string(os.PathSeparator))
178 for len(cleaned) < len(path) {
179 path = cleaned
180 cleaned = strings.TrimRight(strings.TrimSuffix(path, string(os.PathSeparator)+"."), string(os.PathSeparator))
181 }
182
183 base := filepath.Base(path)
184 path = strings.TrimSuffix(path, string(os.PathSeparator)+base)
185
186 resolvedContainerPath, err = pathResolver.resolvePath(path)
187
188 // Error? That is the end
189 if err != nil {
190 if errors.Is(err, os.ErrNotExist) {
191 return nil, errors.Join(errDoesNotExist, err)
192 } else if errors.Is(err, syscall.ENOTDIR) {
193 return nil, errors.Join(errIsNotADir, err)
194 }
195
196 return nil, err

Callers 1

CopyFilesFunction · 0.85

Calls 4

newResolverFunction · 0.85
resolvePathMethod · 0.80
getMountMethod · 0.80
StatMethod · 0.80

Tested by

no test coverage detected

Used in the wild real call sites across dependent graphs

searching dependent graphs…