5
5
"io"
6
6
"os"
7
7
"os/user"
8
+ "path"
8
9
"path/filepath"
9
10
"strconv"
10
11
"strings"
@@ -147,7 +148,7 @@ func copyContainerToContainer(sourceContainer string, sourcePath string, destCon
147
148
sourceContainerTarget := sourceContainerInfo .LinkTarget
148
149
destContainerTarget := destContainerInfo .LinkTarget
149
150
if ! destContainerInfo .IsDir {
150
- destContainerTarget = filepath .Dir (destPath )
151
+ destContainerTarget = path .Dir (destPath )
151
152
}
152
153
153
154
// If we copy a directory via the "." notation and the container path
@@ -158,8 +159,8 @@ func copyContainerToContainer(sourceContainer string, sourcePath string, destCon
158
159
// Hence, whenever "." is the source and the destination does not
159
160
// exist, we copy the source's parent and let the copier package create
160
161
// the destination via the Rename option.
161
- if destResolvedToParentDir && sourceContainerInfo .IsDir && filepath .Base (sourcePath ) == "." {
162
- sourceContainerTarget = filepath .Dir (sourceContainerTarget )
162
+ if destResolvedToParentDir && sourceContainerInfo .IsDir && path .Base (sourcePath ) == "." {
163
+ sourceContainerTarget = path .Dir (sourceContainerTarget )
163
164
}
164
165
165
166
reader , writer := io .Pipe ()
@@ -183,7 +184,7 @@ func copyContainerToContainer(sourceContainer string, sourcePath string, destCon
183
184
if (! sourceContainerInfo .IsDir && ! destContainerInfo .IsDir ) || destResolvedToParentDir {
184
185
// If we're having a file-to-file copy, make sure to
185
186
// rename accordingly.
186
- copyOptions .Rename = map [string ]string {filepath .Base (sourceContainerTarget ): destContainerBaseName }
187
+ copyOptions .Rename = map [string ]string {path .Base (sourceContainerTarget ): destContainerBaseName }
187
188
}
188
189
189
190
copyFunc , err := registry .ContainerEngine ().ContainerCopyFromArchive (registry .Context (), destContainer , destContainerTarget , reader , copyOptions )
@@ -261,8 +262,8 @@ func copyFromContainer(container string, containerPath string, hostPath string)
261
262
// we copy the source's parent and let the copier package create the
262
263
// destination via the Rename option.
263
264
containerTarget := containerInfo .LinkTarget
264
- if resolvedToHostParentDir && containerInfo .IsDir && filepath .Base (containerTarget ) == "." {
265
- containerTarget = filepath .Dir (containerTarget )
265
+ if resolvedToHostParentDir && containerInfo .IsDir && path .Base (containerTarget ) == "." {
266
+ containerTarget = path .Dir (containerTarget )
266
267
}
267
268
268
269
if ! isStdout && containerInfo .IsDir && ! hostInfo .IsDir {
@@ -307,7 +308,7 @@ func copyFromContainer(container string, containerPath string, hostPath string)
307
308
if (! containerInfo .IsDir && ! hostInfo .IsDir ) || resolvedToHostParentDir {
308
309
// If we're having a file-to-file copy, make sure to
309
310
// rename accordingly.
310
- putOptions .Rename = map [string ]string {filepath .Base (containerTarget ): hostBaseName }
311
+ putOptions .Rename = map [string ]string {path .Base (containerTarget ): hostBaseName }
311
312
}
312
313
dir := hostInfo .LinkTarget
313
314
if ! hostInfo .IsDir {
@@ -428,7 +429,11 @@ func copyToContainer(container string, containerPath string, hostPath string) er
428
429
// rename accordingly.
429
430
getOptions .Rename = map [string ]string {filepath .Base (hostTarget ): containerBaseName }
430
431
}
431
- if err := buildahCopiah .Get ("/" , "" , getOptions , []string {hostTarget }, writer ); err != nil {
432
+
433
+ // On Windows, the root path needs to be <drive>:\, while otherwise
434
+ // it needs to be /. Combining filepath.VolumeName() + string(os.PathSeparator)
435
+ // gives us the correct path for the current OS.
436
+ if err := buildahCopiah .Get (filepath .VolumeName (hostTarget )+ string (os .PathSeparator ), "" , getOptions , []string {hostTarget }, writer ); err != nil {
432
437
return fmt .Errorf ("copying from host: %w" , err )
433
438
}
434
439
return nil
@@ -438,7 +443,7 @@ func copyToContainer(container string, containerPath string, hostPath string) er
438
443
defer reader .Close ()
439
444
target := containerInfo .FileInfo .LinkTarget
440
445
if ! containerInfo .IsDir {
441
- target = filepath .Dir (target )
446
+ target = path .Dir (target )
442
447
}
443
448
444
449
copyFunc , err := registry .ContainerEngine ().ContainerCopyFromArchive (registry .Context (), container , target , reader , entities.CopyOptions {Chown : chown , NoOverwriteDirNonDir : ! cpOpts .OverwriteDirNonDir })
@@ -460,7 +465,7 @@ func copyToContainer(container string, containerPath string, hostPath string) er
460
465
func resolvePathOnDestinationContainer (container string , containerPath string , isStdin bool ) (baseName string , containerInfo * entities.ContainerStatReport , resolvedToParentDir bool , err error ) {
461
466
containerInfo , err = registry .ContainerEngine ().ContainerStat (registry .Context (), container , containerPath )
462
467
if err == nil {
463
- baseName = filepath .Base (containerInfo .LinkTarget )
468
+ baseName = path .Base (containerInfo .LinkTarget )
464
469
return //nolint: nilerr
465
470
}
466
471
@@ -476,17 +481,17 @@ func resolvePathOnDestinationContainer(container string, containerPath string, i
476
481
// NOTE: containerInfo may actually be set. That happens when
477
482
// the container path is a symlink into nirvana. In that case,
478
483
// we must use the symlinked path instead.
479
- path := containerPath
484
+ parentPath := containerPath
480
485
if containerInfo != nil {
481
- baseName = filepath .Base (containerInfo .LinkTarget )
482
- path = containerInfo .LinkTarget
486
+ baseName = path .Base (containerInfo .LinkTarget )
487
+ parentPath = containerInfo .LinkTarget
483
488
} else {
484
- baseName = filepath .Base (containerPath )
489
+ baseName = path .Base (containerPath )
485
490
}
486
491
487
- parentDir , err := containerParentDir (container , path )
492
+ parentDir , err := containerParentDir (container , parentPath )
488
493
if err != nil {
489
- err = fmt .Errorf ("could not determine parent dir of %q on container %s: %w" , path , container , err )
494
+ err = fmt .Errorf ("could not determine parent dir of %q on container %s: %w" , parentPath , container , err )
490
495
return
491
496
}
492
497
@@ -504,8 +509,11 @@ func resolvePathOnDestinationContainer(container string, containerPath string, i
504
509
// container. If the path is relative, it will be resolved relative to the
505
510
// container's working directory (or "/" if the work dir isn't set).
506
511
func containerParentDir (container string , containerPath string ) (string , error ) {
507
- if filepath .IsAbs (containerPath ) {
508
- return filepath .Dir (containerPath ), nil
512
+ // This is specifically a path in the (linux) container, so we need to intentionally use
513
+ // path instead of filepath to ensure we don't try to parse container paths using the
514
+ // host OS conventions.
515
+ if path .IsAbs (containerPath ) {
516
+ return path .Dir (containerPath ), nil
509
517
}
510
518
inspectData , _ , err := registry .ContainerEngine ().ContainerInspect (registry .Context (), []string {container }, entities.InspectOptions {})
511
519
if err != nil {
@@ -514,9 +522,9 @@ func containerParentDir(container string, containerPath string) (string, error)
514
522
if len (inspectData ) != 1 {
515
523
return "" , fmt .Errorf ("inspecting container %q: expected 1 data item but got %d" , container , len (inspectData ))
516
524
}
517
- workDir := filepath .Join ("/" , inspectData [0 ].Config .WorkingDir )
518
- workDir = filepath .Join (workDir , containerPath )
519
- return filepath .Dir (workDir ), nil
525
+ workDir := path .Join ("/" , inspectData [0 ].Config .WorkingDir )
526
+ workDir = path .Join (workDir , containerPath )
527
+ return path .Dir (workDir ), nil
520
528
}
521
529
522
530
// validateFileInfo returns an error if the specified FileInfo doesn't point to
0 commit comments