@@ -11,6 +11,7 @@ import (
1111
1212 "github.com/docker/docker/api/types/filters"
1313 "github.com/docker/docker/pkg/system"
14+ "github.com/pkg/errors"
1415 "github.com/spf13/pflag"
1516)
1617
@@ -125,3 +126,36 @@ func AddPlatformFlag(flags *pflag.FlagSet, target *string) {
125126 flags .SetAnnotation ("platform" , "version" , []string {"1.32" })
126127 flags .SetAnnotation ("platform" , "experimental" , nil )
127128}
129+
130+ // ValidateOutputPath validates the output paths of the `export` and `save` commands.
131+ func ValidateOutputPath (path string ) error {
132+ dir := filepath .Dir (path )
133+ if dir != "" && dir != "." {
134+ if _ , err := os .Stat (dir ); os .IsNotExist (err ) {
135+ return errors .Errorf ("invalid output path: directory %q does not exist" , dir )
136+ }
137+ }
138+ // check whether `path` points to a regular file
139+ // (if the path exists and doesn't point to a directory)
140+ if fileInfo , err := os .Stat (path ); ! os .IsNotExist (err ) {
141+ if fileInfo .Mode ().IsDir () || fileInfo .Mode ().IsRegular () {
142+ return nil
143+ }
144+
145+ if err := ValidateOutputPathFileMode (fileInfo .Mode ()); err != nil {
146+ return errors .Wrap (err , fmt .Sprintf ("invalid output path: %q must be a directory or a regular file" , path ))
147+ }
148+ }
149+ return nil
150+ }
151+
152+ // ValidateOutputPathFileMode validates the output paths of the `cp` command and serves as a
153+ // helper to `ValidateOutputPath`
154+ func ValidateOutputPathFileMode (fileMode os.FileMode ) error {
155+ if fileMode & os .ModeDevice != 0 {
156+ return errors .New ("got a device" )
157+ } else if fileMode & os .ModeIrregular != 0 {
158+ return errors .New ("got an irregular file" )
159+ }
160+ return nil
161+ }
0 commit comments