Support for Windows paths in the source position of the volume mounts

There are 2 things added. First there is added support for handling drive
letters while doing value split. If drive letter is detected, then max number
of elements will be increased by one, but then first two will be concatenated
to reconstruct the path. Second part is basic, but working, conversion of Windows
path to Unix path to be used, when target path is not explicitly specified.

Signed-off-by: Arthur Sengileyev <arthur.sengileyev@gmail.com>
This commit is contained in:
Arthur Sengileyev
2023-01-13 23:25:42 +02:00
parent b7987ca2ba
commit 952049fe52
3 changed files with 67 additions and 24 deletions

View File

@ -301,30 +301,10 @@ func (v *MachineVM) Init(opts machine.InitOptions) (bool, error) {
mounts := []machine.Mount{}
for i, volume := range opts.Volumes {
tag := fmt.Sprintf("vol%d", i)
paths := strings.SplitN(volume, ":", 3)
source := paths[0]
target := source
readonly := false
securityModel := "none"
if len(paths) > 1 {
target = paths[1]
}
if len(paths) > 2 {
options := paths[2]
volopts := strings.Split(options, ",")
for _, o := range volopts {
switch {
case o == "rw":
readonly = false
case o == "ro":
readonly = true
case strings.HasPrefix(o, "security_model="):
securityModel = strings.Split(o, "=")[1]
default:
fmt.Printf("Unknown option: %s\n", o)
}
}
}
paths := pathsFromVolume(volume)
source := extractSourcePath(paths)
target := extractTargetPath(paths)
readonly, securityModel := extractMountOptions(paths)
if volumeType == VolumeTypeVirtfs {
virtfsOptions := fmt.Sprintf("local,path=%s,mount_tag=%s,security_model=%s", source, tag, securityModel)
if readonly {
@ -1756,3 +1736,29 @@ func isRootful() bool {
return !rootless.IsRootless() && os.Getuid() != -1
}
func extractSourcePath(paths []string) string {
return paths[0]
}
func extractMountOptions(paths []string) (bool, string) {
readonly := false
securityModel := "none"
if len(paths) > 2 {
options := paths[2]
volopts := strings.Split(options, ",")
for _, o := range volopts {
switch {
case o == "rw":
readonly = false
case o == "ro":
readonly = true
case strings.HasPrefix(o, "security_model="):
securityModel = strings.Split(o, "=")[1]
default:
fmt.Printf("Unknown option: %s\n", o)
}
}
}
return readonly, securityModel
}

View File

@ -6,6 +6,7 @@ package qemu
import (
"bytes"
"fmt"
"strings"
"syscall"
"golang.org/x/sys/unix"
@ -31,3 +32,14 @@ func checkProcessStatus(processHint string, pid int, stderrBuf *bytes.Buffer) er
}
return nil
}
func pathsFromVolume(volume string) []string {
return strings.SplitN(volume, ":", 3)
}
func extractTargetPath(paths []string) string {
if len(paths) > 1 {
return paths[1]
}
return paths[0]
}

View File

@ -3,6 +3,8 @@ package qemu
import (
"bytes"
"fmt"
"regexp"
"strings"
"github.com/containers/podman/v4/pkg/machine"
)
@ -25,3 +27,26 @@ func checkProcessStatus(processHint string, pid int, stderrBuf *bytes.Buffer) er
}
return nil
}
func pathsFromVolume(volume string) []string {
paths := strings.SplitN(volume, ":", 3)
driveLetterMatcher := regexp.MustCompile(`^(?:\\\\[.?]\\)?[a-zA-Z]$`)
if len(paths) > 1 && driveLetterMatcher.MatchString(paths[0]) {
paths = strings.SplitN(volume, ":", 4)
paths = append([]string{paths[0] + ":" + paths[1]}, paths[2:]...)
}
return paths
}
func extractTargetPath(paths []string) string {
if len(paths) > 1 {
return paths[1]
}
target := strings.ReplaceAll(paths[0], "\\", "/")
target = strings.ReplaceAll(target, ":", "/")
if strings.HasPrefix(target, "//./") || strings.HasPrefix(target, "//?/") {
target = target[4:]
}
dedup := regexp.MustCompile(`//+`)
return dedup.ReplaceAllLiteralString("/"+target, "/")
}