diff --git a/go.mod b/go.mod
index 672734f490..9f3c806d0b 100644
--- a/go.mod
+++ b/go.mod
@@ -21,6 +21,7 @@ require (
 	github.com/containers/storage v1.52.1-0.20240202181245-1419a5980565
 	github.com/coreos/go-systemd/v22 v22.5.1-0.20231103132048-7d375ecc2b09
 	github.com/coreos/stream-metadata-go v0.4.4
+	github.com/crc-org/crc/v2 v2.32.0
 	github.com/crc-org/vfkit v0.5.0
 	github.com/cyphar/filepath-securejoin v0.2.4
 	github.com/digitalocean/go-qemu v0.0.0-20230711162256-2e3d0186973e
@@ -104,7 +105,7 @@ require (
 	github.com/coreos/go-oidc/v3 v3.9.0 // indirect
 	github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f // indirect
 	github.com/cyberphone/json-canonicalization v0.0.0-20231217050601-ba74d44ecf5f // indirect
-	github.com/davecgh/go-spew v1.1.1 // indirect
+	github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
 	github.com/digitalocean/go-libvirt v0.0.0-20220804181439-8648fbde413e // indirect
 	github.com/disiqueira/gotree/v3 v3.0.2 // indirect
 	github.com/distribution/reference v0.5.0 // indirect
@@ -148,7 +149,7 @@ require (
 	github.com/jinzhu/copier v0.4.0 // indirect
 	github.com/josharian/intern v1.0.0 // indirect
 	github.com/klauspost/compress v1.17.5 // indirect
-	github.com/klauspost/cpuid/v2 v2.2.5 // indirect
+	github.com/klauspost/cpuid/v2 v2.2.6 // indirect
 	github.com/klauspost/pgzip v1.2.6 // indirect
 	github.com/kr/fs v0.1.0 // indirect
 	github.com/kr/pretty v0.3.1 // indirect
@@ -157,6 +158,7 @@ require (
 	github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
 	github.com/mailru/easyjson v0.7.7 // indirect
 	github.com/manifoldco/promptui v0.9.0 // indirect
+	github.com/mattn/go-colorable v0.1.13 // indirect
 	github.com/mattn/go-isatty v0.0.19 // indirect
 	github.com/mattn/go-runewidth v0.0.15 // indirect
 	github.com/mdlayher/socket v0.4.1 // indirect
@@ -176,7 +178,7 @@ require (
 	github.com/pelletier/go-toml/v2 v2.1.1 // indirect
 	github.com/pkg/errors v0.9.1 // indirect
 	github.com/pkg/sftp v1.13.6 // indirect
-	github.com/pmezard/go-difflib v1.0.0 // indirect
+	github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
 	github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
 	github.com/proglottis/gpgme v0.1.3 // indirect
 	github.com/rivo/uniseg v0.4.4 // indirect
@@ -218,6 +220,7 @@ require (
 	google.golang.org/genproto/googleapis/rpc v0.0.0-20231212172506-995d672761c0 // indirect
 	google.golang.org/grpc v1.60.1 // indirect
 	gopkg.in/go-jose/go-jose.v2 v2.6.1 // indirect
+	gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
 	gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
 	tags.cncf.io/container-device-interface/specs-go v0.6.0 // indirect
 )
diff --git a/go.sum b/go.sum
index 58ffb727fc..f85ef3759c 100644
--- a/go.sum
+++ b/go.sum
@@ -102,6 +102,8 @@ github.com/coreos/go-systemd/v22 v22.5.1-0.20231103132048-7d375ecc2b09/go.mod h1
 github.com/coreos/stream-metadata-go v0.4.4 h1:PM/6iNhofKGydsatiY1zdnMMHBT34skb5P7nfEFR4GU=
 github.com/coreos/stream-metadata-go v0.4.4/go.mod h1:fMObQqQm8Ku91G04btKzEH3AsdP1mrAb986z9aaK0tE=
 github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
+github.com/crc-org/crc/v2 v2.32.0 h1:I/62j5KrID8ua1vgAUPOVTtzhcsCsHWdqqiIRHySLfQ=
+github.com/crc-org/crc/v2 v2.32.0/go.mod h1:Q2XJM3KkR/Gu+tBjeN77pk5P8DWYKdbxCSf+9l9MYcs=
 github.com/crc-org/vfkit v0.5.0 h1:co7N/3h5Jl29VfhPIvbF2cSG2bC7vC4DxbBVeppGPY0=
 github.com/crc-org/vfkit v0.5.0/go.mod h1:OQiqOghCzdgkd/jRoVu4/lcfQSKje7XPVpfW1aO9YvE=
 github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
@@ -111,8 +113,9 @@ github.com/cyberphone/json-canonicalization v0.0.0-20231217050601-ba74d44ecf5f/g
 github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg=
 github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4=
 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
-github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
 github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
+github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/digitalocean/go-libvirt v0.0.0-20220804181439-8648fbde413e h1:SCnqm8SjSa0QqRxXbo5YY//S+OryeJioe17nK+iDZpg=
 github.com/digitalocean/go-libvirt v0.0.0-20220804181439-8648fbde413e/go.mod h1:o129ljs6alsIQTc8d6eweihqpmmrbxZ2g1jhgjhPykI=
 github.com/digitalocean/go-qemu v0.0.0-20230711162256-2e3d0186973e h1:x5PInTuXLddHWHlePCNAcM8QtUfOGx44f3UmYPMtDcI=
@@ -345,8 +348,8 @@ github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47e
 github.com/klauspost/compress v1.17.5 h1:d4vBd+7CHydUqpFBgUEKkSdtSugf9YFmSkvUYPquI5E=
 github.com/klauspost/compress v1.17.5/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM=
 github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
-github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg=
-github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
+github.com/klauspost/cpuid/v2 v2.2.6 h1:ndNyv040zDGIDh8thGkXYjnFtiN02M1PVVF+JE/48xc=
+github.com/klauspost/cpuid/v2 v2.2.6/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
 github.com/klauspost/pgzip v1.2.6 h1:8RXeL5crjEUFnR2/Sn6GJNWtSQ3Dk8pq4CL3jvdDyjU=
 github.com/klauspost/pgzip v1.2.6/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
 github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
@@ -380,6 +383,8 @@ github.com/manifoldco/promptui v0.9.0/go.mod h1:ka04sppxSGFAtxX0qhlYQjISsg9mR4GW
 github.com/markbates/oncer v0.0.0-20181203154359-bf2de49a0be2/go.mod h1:Ld9puTsIW75CHf65OeIOkyKbteujpZVXDpWK6YGZbxE=
 github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0=
 github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
+github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
+github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
 github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
 github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
 github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
@@ -471,8 +476,9 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
 github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
 github.com/pkg/sftp v1.13.6 h1:JFZT4XbOU7l77xGSpOdW+pwIMqP044IyjXX6FGyEKFo=
 github.com/pkg/sftp v1.13.6/go.mod h1:tz1ryNURKu77RL+GuCzmoJYxQczL3wLNNpPWagdg4Qk=
-github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
+github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
 github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw=
 github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
 github.com/proglottis/gpgme v0.1.3 h1:Crxx0oz4LKB3QXc5Ea0J19K/3ICfy3ftr5exgUK1AU0=
@@ -717,6 +723,7 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc
 golang.org/x/sys v0.0.0-20220622161953-175b2fd9d664/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220817070843-5a390386f1f2/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@@ -808,6 +815,8 @@ gopkg.in/go-jose/go-jose.v2 v2.6.1 h1:qEzJlIDmG9q5VO0M/o8tGS65QMHMS1w01TQJB1VPJ4
 gopkg.in/go-jose/go-jose.v2 v2.6.1/go.mod h1:zzZDPkNNw/c9IE7Z9jr11mBZQhKQTMzoEEIoEdZlFBI=
 gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
 gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
+gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=
+gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc=
 gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
 gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
 gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
@@ -826,16 +835,16 @@ gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
 gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU=
 honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
 honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
-k8s.io/apimachinery v0.26.5 h1:hTQVhJao2piX7vSgCn4Lwd6E0o/+TJIH4NqRf+q4EmE=
+k8s.io/apimachinery v0.27.4 h1:CdxflD4AF61yewuid0fLl6bM4a3q04jWel0IlP+aYjs=
 k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8=
 k8s.io/klog/v2 v2.100.1 h1:7WCHKK6K8fNhTqfBhISHQ97KrnJNFZMcQvKp7gP/tmg=
 k8s.io/kubernetes v1.28.4 h1:aRNxs5jb8FVTtlnxeA4FSDBVKuFwA8Gw40/U2zReBYA=
 k8s.io/kubernetes v1.28.4/go.mod h1:BTzDCKYAlu6LL9ITbfjwgwIrJ30hlTgbv0eXDoA/WoA=
-k8s.io/utils v0.0.0-20230505201702-9f6742963106 h1:EObNQ3TW2D+WptiYXlApGNLVy0zm/JIBVY9i+M4wpAU=
+k8s.io/utils v0.0.0-20230711102312-30195339c3c7 h1:ZgnF1KZsYxWIifwSNZFZgNtWE89WI5yiP5WwlfDoIyc=
 nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=
 rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
 sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo=
-sigs.k8s.io/structured-merge-diff/v4 v4.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE=
+sigs.k8s.io/structured-merge-diff/v4 v4.3.0 h1:UZbZAZfX0wV2zr7YZorDz6GXROfDFj6LvqCRm4VUVKk=
 sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
 sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=
 src.elv.sh v0.16.0-rc1.0.20220116211855-fda62502ad7f h1:pjVeIo9Ba6K1Wy+rlwX91zT7A+xGEmxiNRBdN04gDTQ=
diff --git a/pkg/machine/compression/copy_test.go b/pkg/machine/compression/copy_test.go
index 9c25535ec5..1344211c5c 100644
--- a/pkg/machine/compression/copy_test.go
+++ b/pkg/machine/compression/copy_test.go
@@ -4,6 +4,8 @@ import (
 	"os"
 	"path/filepath"
 	"testing"
+
+	crcOs "github.com/crc-org/crc/v2/pkg/os"
 )
 
 func TestCopyFile(t *testing.T) {
@@ -37,7 +39,7 @@ func TestCopyFile(t *testing.T) {
 
 	destFilePath := filepath.Join(os.TempDir(), destFi.Name())
 
-	if err := CopyFile(srcFilePath, destFilePath); err != nil {
+	if err := crcOs.CopyFile(srcFilePath, destFilePath); err != nil {
 		t.Fatal(err)
 	}
 
diff --git a/pkg/machine/compression/decompress.go b/pkg/machine/compression/decompress.go
index 21b04fb581..14a6d526de 100644
--- a/pkg/machine/compression/decompress.go
+++ b/pkg/machine/compression/decompress.go
@@ -17,6 +17,7 @@ import (
 	"github.com/containers/podman/v5/pkg/machine/define"
 	"github.com/containers/podman/v5/utils"
 	"github.com/containers/storage/pkg/archive"
+	crcOs "github.com/crc-org/crc/v2/pkg/os"
 	"github.com/sirupsen/logrus"
 	"github.com/ulikunitz/xz"
 )
@@ -59,7 +60,7 @@ func Decompress(localPath *define.VMFile, uncompressedPath string) error {
 			return err
 		}
 		fmt.Printf("Copying uncompressed file %q to %q/n", localPath.GetPath(), dstFile.Name())
-		_, err = CopySparse(uncompressedFileWriter, dstFile)
+		_, err = crcOs.CopySparse(uncompressedFileWriter, dstFile)
 		return err
 	case archive.Gzip:
 		if runtime.GOOS == "darwin" {
@@ -271,7 +272,7 @@ func decompressGzWithSparse(prefix string, compressedPath *define.VMFile, uncomp
 	// }()
 
 	logrus.Debugf("decompressing %s", compressedPath.GetPath())
-	_, err = CopySparse(dstFile, gzReader)
+	_, err = crcOs.CopySparse(dstFile, gzReader)
 	logrus.Debug("decompression complete")
 	// p.Wait()
 	return err
diff --git a/pkg/machine/e2e/machine_test.go b/pkg/machine/e2e/machine_test.go
index 76a8fc1a83..e109532bac 100644
--- a/pkg/machine/e2e/machine_test.go
+++ b/pkg/machine/e2e/machine_test.go
@@ -18,6 +18,7 @@ import (
 	"github.com/containers/podman/v5/pkg/machine/provider"
 	"github.com/containers/podman/v5/pkg/machine/vmconfigs"
 	"github.com/containers/podman/v5/utils"
+	crcOs "github.com/crc-org/crc/v2/pkg/os"
 	. "github.com/onsi/ginkgo/v2"
 	. "github.com/onsi/gomega"
 )
@@ -168,7 +169,7 @@ func setup() (string, *machineTestBuilder) {
 			Fail(fmt.Sprintf("failed to copy %ss to %s: %q", fqImageName, mb.imagePath, err))
 		}
 	} else {
-		if _, err := compression.CopySparse(dest, src); err != nil {
+		if _, err := crcOs.CopySparse(dest, src); err != nil {
 			Fail(fmt.Sprintf("failed to copy %q to %q: %q", src.Name(), dest.Name(), err))
 		}
 	}
diff --git a/vendor/github.com/crc-org/crc/v2/LICENSE b/vendor/github.com/crc-org/crc/v2/LICENSE
new file mode 100644
index 0000000000..1405b983c0
--- /dev/null
+++ b/vendor/github.com/crc-org/crc/v2/LICENSE
@@ -0,0 +1,191 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   Copyright 2019 Red Hat, Inc.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
diff --git a/vendor/github.com/crc-org/crc/v2/pkg/crc/logging/inmemory.go b/vendor/github.com/crc-org/crc/v2/pkg/crc/logging/inmemory.go
new file mode 100644
index 0000000000..8d48f9256b
--- /dev/null
+++ b/vendor/github.com/crc-org/crc/v2/pkg/crc/logging/inmemory.go
@@ -0,0 +1,44 @@
+package logging
+
+import (
+	"container/ring"
+	"sync"
+
+	"github.com/sirupsen/logrus"
+)
+
+// This hook keeps in memory n messages from error to info level
+type inMemoryHook struct {
+	messages *ring.Ring
+	lock     sync.RWMutex
+}
+
+func newInMemoryHook(size int) *inMemoryHook {
+	return &inMemoryHook{
+		messages: ring.New(size),
+	}
+}
+
+func (h *inMemoryHook) Levels() []logrus.Level {
+	return []logrus.Level{logrus.InfoLevel, logrus.WarnLevel, logrus.ErrorLevel}
+}
+
+func (h *inMemoryHook) Fire(entry *logrus.Entry) error {
+	h.lock.Lock()
+	defer h.lock.Unlock()
+	h.messages.Value = entry.Message
+	h.messages = h.messages.Next()
+	return nil
+}
+
+func (h *inMemoryHook) Messages() []string {
+	h.lock.RLock()
+	defer h.lock.RUnlock()
+	var ret []string
+	h.messages.Do(func(elem interface{}) {
+		if str, ok := elem.(string); ok {
+			ret = append(ret, str)
+		}
+	})
+	return ret
+}
diff --git a/vendor/github.com/crc-org/crc/v2/pkg/crc/logging/logging.go b/vendor/github.com/crc-org/crc/v2/pkg/crc/logging/logging.go
new file mode 100644
index 0000000000..a58ac42785
--- /dev/null
+++ b/vendor/github.com/crc-org/crc/v2/pkg/crc/logging/logging.go
@@ -0,0 +1,126 @@
+package logging
+
+import (
+	"os"
+
+	"github.com/sirupsen/logrus"
+	"github.com/spf13/pflag"
+	terminal "golang.org/x/term"
+	"gopkg.in/natefinch/lumberjack.v2"
+)
+
+var (
+	lumberjackLogger *lumberjack.Logger
+	logLevel         = defaultLogLevel()
+	Memory           = newInMemoryHook(100)
+)
+
+func CloseLogging() {
+	if lumberjackLogger != nil {
+		_ = lumberjackLogger.Close()
+	}
+	logrus.StandardLogger().ReplaceHooks(make(logrus.LevelHooks))
+}
+
+func BackupLogFile() {
+	if lumberjackLogger == nil {
+		return
+	}
+	_ = lumberjackLogger.Rotate()
+}
+
+func InitLogrus(logFilePath string) {
+	if lumberjackLogger != nil {
+		return
+	}
+
+	lumberjackLogger = &lumberjack.Logger{
+		Filename:   logFilePath,
+		MaxSize:    5, // 5MB
+		MaxBackups: 2,
+	}
+	// send logs to file
+	logrus.SetOutput(lumberjackLogger)
+
+	logrus.SetLevel(logrus.TraceLevel)
+
+	level, err := logrus.ParseLevel(logLevel)
+	if err != nil {
+		level = logrus.InfoLevel
+	}
+
+	logrus.AddHook(Memory)
+
+	// Add hook to send error/fatal to stderr
+	logrus.AddHook(newstdErrHook(level, &logrus.TextFormatter{
+		ForceColors:            terminal.IsTerminal(int(os.Stderr.Fd())),
+		DisableTimestamp:       true,
+		DisableLevelTruncation: false,
+	}))
+}
+
+func DefaultLogLevel() logrus.Level {
+	level, err := logrus.ParseLevel(logLevel)
+	if err != nil {
+		level = logrus.InfoLevel
+	}
+	return level
+}
+
+func defaultLogLevel() string {
+	defaultLevel := "info"
+	envLogLevel := os.Getenv("CRC_LOG_LEVEL")
+	if envLogLevel != "" {
+		defaultLevel = envLogLevel
+	}
+
+	return defaultLevel
+}
+
+func AddLogLevelFlag(flagset *pflag.FlagSet) {
+	flagset.StringVar(&logLevel, "log-level", defaultLogLevel(), "log level (e.g. \"debug | info | warn | error\")")
+}
+
+func IsDebug() bool {
+	return logLevel == "debug"
+}
+
+func Info(args ...interface{}) {
+	logrus.Info(args...)
+}
+
+func Infof(s string, args ...interface{}) {
+	logrus.Infof(s, args...)
+}
+
+func Warn(args ...interface{}) {
+	logrus.Warn(args...)
+}
+
+func Warnf(s string, args ...interface{}) {
+	logrus.Warnf(s, args...)
+}
+
+func Fatal(args ...interface{}) {
+	logrus.Fatal(args...)
+}
+
+func Fatalf(s string, args ...interface{}) {
+	logrus.Fatalf(s, args...)
+}
+
+func Error(args ...interface{}) {
+	logrus.Error(args...)
+}
+
+func Errorf(s string, args ...interface{}) {
+	logrus.Errorf(s, args...)
+}
+
+func Debug(args ...interface{}) {
+	logrus.Debug(args...)
+}
+
+func Debugf(s string, args ...interface{}) {
+	logrus.Debugf(s, args...)
+}
diff --git a/vendor/github.com/crc-org/crc/v2/pkg/crc/logging/stderr_hook.go b/vendor/github.com/crc-org/crc/v2/pkg/crc/logging/stderr_hook.go
new file mode 100644
index 0000000000..e9c593667f
--- /dev/null
+++ b/vendor/github.com/crc-org/crc/v2/pkg/crc/logging/stderr_hook.go
@@ -0,0 +1,53 @@
+package logging
+
+import (
+	"io"
+	"os"
+	"runtime"
+
+	"github.com/mattn/go-colorable"
+	"github.com/sirupsen/logrus"
+)
+
+// This is stdErrHook to send error to the stdErr.
+type stdErrHook struct {
+	stderr    io.Writer
+	formatter logrus.Formatter
+	level     logrus.Level
+}
+
+func newstdErrHook(level logrus.Level, formatter logrus.Formatter) *stdErrHook {
+	// For windows to display colors we need to use the go-colorable writer
+	if runtime.GOOS == "windows" {
+		return &stdErrHook{
+			stderr:    colorable.NewColorableStderr(),
+			formatter: formatter,
+			level:     level,
+		}
+	}
+	return &stdErrHook{
+		stderr:    os.Stderr,
+		formatter: formatter,
+		level:     level,
+	}
+}
+
+func (h stdErrHook) Levels() []logrus.Level {
+	var levels []logrus.Level
+	for _, level := range logrus.AllLevels {
+		if level <= h.level {
+			levels = append(levels, level)
+		}
+	}
+	return levels
+}
+
+func (h *stdErrHook) Fire(entry *logrus.Entry) error {
+	line, err := h.formatter.Format(entry)
+	if err != nil {
+		return err
+	}
+
+	_, err = h.stderr.Write(line)
+	return err
+}
diff --git a/pkg/machine/compression/copy.go b/vendor/github.com/crc-org/crc/v2/pkg/os/copy.go
similarity index 88%
rename from pkg/machine/compression/copy.go
rename to vendor/github.com/crc-org/crc/v2/pkg/os/copy.go
index 2e4637865c..4c7d9e3a06 100644
--- a/pkg/machine/compression/copy.go
+++ b/vendor/github.com/crc-org/crc/v2/pkg/os/copy.go
@@ -1,4 +1,4 @@
-package compression
+package os
 
 import (
 	"bytes"
@@ -6,12 +6,6 @@ import (
 	"os"
 )
 
-// TODO vendor this in ... pkg/os directory is small and code should be negligible
-/*
-	NOTE:   copy.go and copy.test were lifted from github.com/crc-org/crc because
-			i was having trouble getting go to vendor it properly. all credit to them
-*/
-
 func copyFile(src, dst string, sparse bool) error {
 	in, err := os.Open(src)
 	if err != nil {
diff --git a/vendor/github.com/crc-org/crc/v2/pkg/os/exec.go b/vendor/github.com/crc-org/crc/v2/pkg/os/exec.go
new file mode 100644
index 0000000000..130b1680da
--- /dev/null
+++ b/vendor/github.com/crc-org/crc/v2/pkg/os/exec.go
@@ -0,0 +1,86 @@
+package os
+
+import (
+	"bytes"
+	"errors"
+	"os"
+	"os/exec"
+	"strings"
+
+	"github.com/crc-org/crc/v2/pkg/crc/logging"
+)
+
+func runCmd(command string, args []string, env map[string]string) (string, string, error) {
+	cmd := exec.Command(command, args...) // #nosec G204
+	if len(env) != 0 {
+		cmd.Env = os.Environ()
+		for key, value := range env {
+			cmd.Env = ReplaceOrAddEnv(cmd.Env, key, value)
+		}
+	}
+	stdOut := new(bytes.Buffer)
+	stdErr := new(bytes.Buffer)
+	cmd.Stdout = stdOut
+	cmd.Stderr = stdErr
+	err := cmd.Run()
+	if err != nil {
+		logging.Debugf("Command failed: %v", err)
+		logging.Debugf("stdout: %s", stdOut.String())
+		logging.Debugf("stderr: %s", stdErr.String())
+	}
+	return stdOut.String(), stdErr.String(), err
+}
+
+func run(command string, args []string, env map[string]string) (string, string, error) {
+	logging.Debugf("Running '%s %s'", command, strings.Join(args, " "))
+	return runCmd(command, args, env)
+}
+
+func runPrivate(command string, args []string, env map[string]string) (string, string, error) {
+	logging.Debugf("Running '%s <hidden arguments>'", command)
+	return runCmd(command, args, env)
+}
+
+// RunPrivileged executes a command using sudo
+// provide a reason why root is needed as the first argument
+func RunPrivileged(reason string, cmdAndArgs ...string) (string, string, error) {
+	sudo, err := exec.LookPath("sudo")
+	if err != nil {
+		return "", "", errors.New("sudo executable not found")
+	}
+	logging.Infof("Using root access: %s", reason)
+	return run(sudo, cmdAndArgs, map[string]string{})
+}
+
+var defaultLocaleEnv = map[string]string{"LC_ALL": "C", "LANG": "C"}
+
+func RunWithDefaultLocale(command string, args ...string) (string, string, error) {
+	return run(command, args, defaultLocaleEnv)
+}
+
+func RunWithDefaultLocalePrivate(command string, args ...string) (string, string, error) {
+	return runPrivate(command, args, defaultLocaleEnv)
+}
+
+type CommandRunner interface {
+	Run(command string, args ...string) (string, string, error)
+	RunPrivate(command string, args ...string) (string, string, error)
+	RunPrivileged(reason string, cmdAndArgs ...string) (string, string, error)
+}
+type localRunner struct{}
+
+func (r *localRunner) Run(command string, args ...string) (string, string, error) {
+	return RunWithDefaultLocale(command, args...)
+}
+
+func (r *localRunner) RunPrivate(command string, args ...string) (string, string, error) {
+	return RunWithDefaultLocalePrivate(command, args...)
+}
+
+func (r *localRunner) RunPrivileged(reason string, cmdAndArgs ...string) (string, string, error) {
+	return RunPrivileged(reason, cmdAndArgs...)
+}
+
+func NewLocalCommandRunner() CommandRunner {
+	return &localRunner{}
+}
diff --git a/vendor/github.com/crc-org/crc/v2/pkg/os/execerror.go b/vendor/github.com/crc-org/crc/v2/pkg/os/execerror.go
new file mode 100644
index 0000000000..303dd41bd3
--- /dev/null
+++ b/vendor/github.com/crc-org/crc/v2/pkg/os/execerror.go
@@ -0,0 +1,57 @@
+/*
+Copyright 2014 The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package os
+
+// ExitError is an interface that presents an API similar to os.ProcessState, which is
+// what ExitError from os/exec is.  This is designed to make testing a bit easier and
+// probably loses some of the cross-platform properties of the underlying library.
+type ExitError interface {
+	String() string
+	Error() string
+	Exited() bool
+	ExitStatus() int
+	Unwrap() error
+}
+
+// CodeExitError is an implementation of ExitError consisting of an error object
+// and an exit code (the upper bits of os.exec.ExitStatus).
+type CodeExitError struct {
+	Err  error
+	Code int
+}
+
+var _ ExitError = CodeExitError{}
+
+func (e CodeExitError) Error() string {
+	return e.Err.Error()
+}
+
+func (e CodeExitError) String() string {
+	return e.Err.Error()
+}
+
+func (e CodeExitError) Exited() bool {
+	return true
+}
+
+func (e CodeExitError) ExitStatus() int {
+	return e.Code
+}
+
+func (e CodeExitError) Unwrap() error {
+	return e.Err
+}
diff --git a/vendor/github.com/crc-org/crc/v2/pkg/os/util.go b/vendor/github.com/crc-org/crc/v2/pkg/os/util.go
new file mode 100644
index 0000000000..df097312c6
--- /dev/null
+++ b/vendor/github.com/crc-org/crc/v2/pkg/os/util.go
@@ -0,0 +1,129 @@
+package os
+
+import (
+	"bytes"
+	"fmt"
+	"io"
+	"os"
+	"path/filepath"
+	"strings"
+
+	"github.com/crc-org/crc/v2/pkg/crc/logging"
+)
+
+// ReplaceOrAddEnv changes the value of an environment variable if it exists otherwise add the new variable
+// It drops the existing value and appends the new value in-place
+func ReplaceOrAddEnv(variables []string, varName string, value string) []string {
+	var result []string
+
+	found := false
+	for _, e := range variables {
+		pair := strings.Split(e, "=")
+		if pair[0] != varName {
+			result = append(result, e)
+		} else {
+			found = true
+			result = append(result, fmt.Sprintf("%s=%s", varName, value))
+		}
+	}
+
+	if !found {
+		result = append(result, fmt.Sprintf("%s=%s", varName, value))
+	}
+	return result
+}
+
+func CopyFileContents(src string, dst string, permission os.FileMode) error {
+	logging.Debugf("Copying '%s' to '%s'", src, dst)
+	srcFile, err := os.Open(filepath.Clean(src))
+	if err != nil {
+		return fmt.Errorf("[%v] Cannot open src file '%s'", err, src)
+	}
+	defer srcFile.Close()
+
+	destFile, err := os.OpenFile(dst, os.O_RDWR|os.O_CREATE, permission)
+	if err != nil {
+		return fmt.Errorf("[%v] Cannot create dst file '%s'", err, dst)
+	}
+	defer destFile.Close()
+
+	_, err = io.Copy(destFile, srcFile)
+	if err != nil {
+		return fmt.Errorf("[%v] Cannot copy '%s' to '%s'", err, src, dst)
+	}
+
+	err = destFile.Sync()
+	if err != nil {
+		return fmt.Errorf("[%v] Cannot sync '%s' to '%s'", err, src, dst)
+	}
+
+	return destFile.Close()
+}
+
+func FileContentMatches(path string, expectedContent []byte) error {
+	_, err := os.Stat(path)
+	if err != nil {
+		return fmt.Errorf("File not found: %s: %s", path, err.Error())
+	}
+	content, err := os.ReadFile(filepath.Clean(path))
+	if err != nil {
+		return fmt.Errorf("Error opening file: %s: %s", path, err.Error())
+	}
+	if !bytes.Equal(content, expectedContent) {
+		return fmt.Errorf("File has unexpected content: %s", path)
+
+	}
+	return nil
+}
+
+func WriteFileIfContentChanged(path string, newContent []byte, perm os.FileMode) (bool, error) {
+	err := FileContentMatches(path, newContent)
+	if err == nil {
+		return false, nil
+	}
+
+	/* Intentionally ignore errors, just try to write the file if we can't read it */
+	err = os.WriteFile(path, newContent, perm)
+
+	if err != nil {
+		return false, err
+	}
+	return true, nil
+}
+
+// FileExists returns true if the file at path exists.
+// It returns false if it does not exist, or if there was an error when checking for its existence.
+// This means there can be false negatives if Lstat fails because of permission issues (file exists,
+// but is not reachable by the current user)
+func FileExists(path string) bool {
+	info, err := os.Lstat(path)
+	if err != nil {
+		return false
+	}
+	return !info.IsDir()
+}
+
+func RemoveFileIfExists(path string) error {
+	if FileExists(path) {
+		return os.Remove(path)
+	}
+	return nil
+}
+
+func RunningUsingSSH() bool {
+	return os.Getenv("SSH_TTY") != ""
+}
+
+// RemoveFileGlob takes a glob pattern as string to remove the files and directories that matches
+func RemoveFileGlob(glob string) error {
+	matchedFiles, err := filepath.Glob(glob)
+	if err != nil {
+		return fmt.Errorf("Unable to find matches: %w", err)
+	}
+	for _, file := range matchedFiles {
+		if err = os.RemoveAll(file); err != nil {
+			return fmt.Errorf("Failed to delete file: %w", err)
+		}
+	}
+	return nil
+}
diff --git a/vendor/github.com/crc-org/crc/v2/pkg/os/util_unix.go b/vendor/github.com/crc-org/crc/v2/pkg/os/util_unix.go
new file mode 100644
index 0000000000..0d1528166d
--- /dev/null
+++ b/vendor/github.com/crc-org/crc/v2/pkg/os/util_unix.go
@@ -0,0 +1,48 @@
+//go:build !windows
+// +build !windows
+
+package os
+
+import (
+	"bytes"
+	"fmt"
+	"os"
+	"os/exec"
+	"os/user"
+	"strconv"
+	"strings"
+
+	"github.com/crc-org/crc/v2/pkg/crc/logging"
+)
+
+func WriteToFileAsRoot(reason, content, filepath string, mode os.FileMode) error {
+	logging.Infof("Using root access: %s", reason)
+	cmd := exec.Command("sudo", "tee", filepath) // #nosec G204
+	cmd.Stdin = strings.NewReader(content)
+	buf := new(bytes.Buffer)
+	cmd.Stderr = buf
+	if err := cmd.Run(); err != nil {
+		return fmt.Errorf("Failed writing to file as root: %s: %s: %v", filepath, buf.String(), err)
+	}
+	if _, _, err := RunPrivileged(fmt.Sprintf("Changing permissions for %s to %o ", filepath, mode),
+		"chmod", strconv.FormatUint(uint64(mode), 8), filepath); err != nil {
+		return err
+	}
+	return nil
+}
+
+func RemoveFileAsRoot(reason, filepath string) error {
+	if !FileExists(filepath) {
+		return nil
+	}
+	_, _, err := RunPrivileged(reason, "rm", "-fr", filepath)
+	return err
+}
+
+func GetCurrentUsername() (string, error) {
+	u, err := user.Current()
+	if err != nil {
+		return "", err
+	}
+	return u.Username, nil
+}
diff --git a/vendor/github.com/crc-org/crc/v2/pkg/os/util_windows.go b/vendor/github.com/crc-org/crc/v2/pkg/os/util_windows.go
new file mode 100644
index 0000000000..7d8f0e8313
--- /dev/null
+++ b/vendor/github.com/crc-org/crc/v2/pkg/os/util_windows.go
@@ -0,0 +1,46 @@
+package os
+
+import (
+	"bytes"
+	"errors"
+	"io"
+	"os"
+	"os/user"
+	"strings"
+
+	"golang.org/x/text/encoding/unicode"
+	"golang.org/x/text/transform"
+)
+
+// ReadFileUTF16LE reads a UTF-16LE file and returns in a []byte
+// ini/inf files in windows are of this format, reading a UTF-16
+// file directly without this would result in malformed texts
+func ReadFileUTF16LE(filename string) ([]byte, error) {
+	// Read the file into a []byte
+	raw, err := os.ReadFile(filename)
+	if err != nil {
+		return nil, err
+	}
+
+	// Make an tranformer that converts MS-Win default to UTF8
+	win16le := unicode.UTF16(unicode.LittleEndian, unicode.IgnoreBOM)
+	// Make a transformer that is like win16le, but abides by BOM
+	utf16bom := unicode.BOMOverride(win16le.NewDecoder())
+
+	// Make a Reader that uses utf16bom
+	unicodeReader := transform.NewReader(bytes.NewReader(raw), utf16bom)
+	decoded, err := io.ReadAll(unicodeReader)
+	return decoded, err
+}
+
+func GetCurrentUsername() (string, error) {
+	u, err := user.Current()
+	if err != nil {
+		return "", err
+	}
+	userAndDomain := strings.Split(u.Username, "\\")
+	if len(userAndDomain) > 1 {
+		return userAndDomain[1], nil
+	}
+	return "", errors.New("unable to find the username of current user")
+}
diff --git a/vendor/github.com/klauspost/cpuid/v2/README.md b/vendor/github.com/klauspost/cpuid/v2/README.md
index accd7abaf9..30f8d2963e 100644
--- a/vendor/github.com/klauspost/cpuid/v2/README.md
+++ b/vendor/github.com/klauspost/cpuid/v2/README.md
@@ -9,10 +9,7 @@ You can access the CPU information by accessing the shared CPU variable of the c
 Package home: https://github.com/klauspost/cpuid
 
 [![PkgGoDev](https://pkg.go.dev/badge/github.com/klauspost/cpuid)](https://pkg.go.dev/github.com/klauspost/cpuid/v2)
-[![Build Status][3]][4]
-
-[3]: https://travis-ci.org/klauspost/cpuid.svg?branch=master
-[4]: https://travis-ci.org/klauspost/cpuid
+[![Go](https://github.com/klauspost/cpuid/actions/workflows/go.yml/badge.svg)](https://github.com/klauspost/cpuid/actions/workflows/go.yml)
 
 ## installing
 
@@ -285,7 +282,12 @@ Exit Code 1
 | AMXINT8            | Tile computational operations on 8-bit integers                                                                                                                                    |
 | AMXFP16            | Tile computational operations on FP16 numbers                                                                                                                                      |
 | AMXTILE            | Tile architecture                                                                                                                                                                  |
+| APX_F              | Intel APX                                                                                                                                                                          |
 | AVX                | AVX functions                                                                                                                                                                      |
+| AVX10              | If set the Intel AVX10 Converged Vector ISA is supported                                                                                                                           |
+| AVX10_128          | If set indicates that AVX10 128-bit vector support is present                                                                                                                      |
+| AVX10_256          | If set indicates that AVX10 256-bit vector support is present                                                                                                                      |
+| AVX10_512          | If set indicates that AVX10 512-bit vector support is present                                                                                                                      |
 | AVX2               | AVX2 functions                                                                                                                                                                     |
 | AVX512BF16         | AVX-512 BFLOAT16 Instructions                                                                                                                                                      |
 | AVX512BITALG       | AVX-512 Bit Algorithms                                                                                                                                                             |
@@ -365,6 +367,8 @@ Exit Code 1
 | IDPRED_CTRL        | IPRED_DIS                                                                                                                                                                          |
 | INT_WBINVD         | WBINVD/WBNOINVD are interruptible.                                                                                                                                                 |
 | INVLPGB            | NVLPGB and TLBSYNC instruction supported                                                                                                                                           |
+| KEYLOCKER          | Key locker                                                                                                                                                                         |
+| KEYLOCKERW         | Key locker wide                                                                                                                                                                    |
 | LAHF               | LAHF/SAHF in long mode                                                                                                                                                             |
 | LAM                | If set, CPU supports Linear Address Masking                                                                                                                                        |
 | LBRVIRT            | LBR virtualization                                                                                                                                                                 |
@@ -380,7 +384,7 @@ Exit Code 1
 | MOVDIRI            | Move Doubleword as Direct Store                                                                                                                                                    |
 | MOVSB_ZL           | Fast Zero-Length MOVSB                                                                                                                                                             |
 | MPX                | Intel MPX (Memory Protection Extensions)                                                                                                                                           |
-| MOVU               | MOVU SSE instructions are more efficient and should be preferred to SSE	MOVL/MOVH. MOVUPS is more efficient than MOVLPS/MOVHPS. MOVUPD is more efficient than MOVLPD/MOVHPD       |
+| MOVU               | MOVU SSE instructions are more efficient and should be preferred to SSE	MOVL/MOVH. MOVUPS is more efficient than MOVLPS/MOVHPS. MOVUPD is more efficient than MOVLPD/MOVHPD        |
 | MSRIRC             | Instruction Retired Counter MSR available                                                                                                                                          |
 | MSRLIST            | Read/Write List of Model Specific Registers                                                                                                                                        |
 | MSR_PAGEFLUSH      | Page Flush MSR available                                                                                                                                                           |
diff --git a/vendor/github.com/klauspost/cpuid/v2/cpuid.go b/vendor/github.com/klauspost/cpuid/v2/cpuid.go
index d015c744e8..15b760337a 100644
--- a/vendor/github.com/klauspost/cpuid/v2/cpuid.go
+++ b/vendor/github.com/klauspost/cpuid/v2/cpuid.go
@@ -76,7 +76,12 @@ const (
 	AMXFP16                             // Tile computational operations on FP16 numbers
 	AMXINT8                             // Tile computational operations on 8-bit integers
 	AMXTILE                             // Tile architecture
+	APX_F                               // Intel APX
 	AVX                                 // AVX functions
+	AVX10                               // If set the Intel AVX10 Converged Vector ISA is supported
+	AVX10_128                           // If set indicates that AVX10 128-bit vector support is present
+	AVX10_256                           // If set indicates that AVX10 256-bit vector support is present
+	AVX10_512                           // If set indicates that AVX10 512-bit vector support is present
 	AVX2                                // AVX2 functions
 	AVX512BF16                          // AVX-512 BFLOAT16 Instructions
 	AVX512BITALG                        // AVX-512 Bit Algorithms
@@ -156,6 +161,8 @@ const (
 	IDPRED_CTRL                         // IPRED_DIS
 	INT_WBINVD                          // WBINVD/WBNOINVD are interruptible.
 	INVLPGB                             // NVLPGB and TLBSYNC instruction supported
+	KEYLOCKER                           // Key locker
+	KEYLOCKERW                          // Key locker wide
 	LAHF                                // LAHF/SAHF in long mode
 	LAM                                 // If set, CPU supports Linear Address Masking
 	LBRVIRT                             // LBR virtualization
@@ -302,9 +309,10 @@ type CPUInfo struct {
 		L2  int // L2 Cache (per core or shared). Will be -1 if undetected
 		L3  int // L3 Cache (per core, per ccx or shared). Will be -1 if undetected
 	}
-	SGX       SGXSupport
-	maxFunc   uint32
-	maxExFunc uint32
+	SGX        SGXSupport
+	AVX10Level uint8
+	maxFunc    uint32
+	maxExFunc  uint32
 }
 
 var cpuid func(op uint32) (eax, ebx, ecx, edx uint32)
@@ -1165,6 +1173,7 @@ func support() flagSet {
 		fs.setIf(ecx&(1<<10) != 0, VPCLMULQDQ)
 		fs.setIf(ecx&(1<<13) != 0, TME)
 		fs.setIf(ecx&(1<<25) != 0, CLDEMOTE)
+		fs.setIf(ecx&(1<<23) != 0, KEYLOCKER)
 		fs.setIf(ecx&(1<<27) != 0, MOVDIRI)
 		fs.setIf(ecx&(1<<28) != 0, MOVDIR64B)
 		fs.setIf(ecx&(1<<29) != 0, ENQCMD)
@@ -1202,6 +1211,8 @@ func support() flagSet {
 		fs.setIf(edx1&(1<<4) != 0, AVXVNNIINT8)
 		fs.setIf(edx1&(1<<5) != 0, AVXNECONVERT)
 		fs.setIf(edx1&(1<<14) != 0, PREFETCHI)
+		fs.setIf(edx1&(1<<19) != 0, AVX10)
+		fs.setIf(edx1&(1<<21) != 0, APX_F)
 
 		// Only detect AVX-512 features if XGETBV is supported
 		if c&((1<<26)|(1<<27)) == (1<<26)|(1<<27) {
@@ -1252,6 +1263,19 @@ func support() flagSet {
 		fs.setIf(edx&(1<<4) != 0, BHI_CTRL)
 		fs.setIf(edx&(1<<5) != 0, MCDT_NO)
 
+		// Add keylocker features.
+		if fs.inSet(KEYLOCKER) && mfi >= 0x19 {
+			_, ebx, _, _ := cpuidex(0x19, 0)
+			fs.setIf(ebx&5 == 5, KEYLOCKERW) // Bit 0 and 2 (1+4)
+		}
+
+		// Add AVX10 features.
+		if fs.inSet(AVX10) && mfi >= 0x24 {
+			_, ebx, _, _ := cpuidex(0x24, 0)
+			fs.setIf(ebx&(1<<16) != 0, AVX10_128)
+			fs.setIf(ebx&(1<<17) != 0, AVX10_256)
+			fs.setIf(ebx&(1<<18) != 0, AVX10_512)
+		}
 	}
 
 	// Processor Extended State Enumeration Sub-leaf (EAX = 0DH, ECX = 1)
@@ -1394,6 +1418,20 @@ func support() flagSet {
 		fs.setIf((a>>24)&1 == 1, VMSA_REGPROT)
 	}
 
+	if mfi >= 0x20 {
+		// Microsoft has decided to purposefully hide the information
+		// of the guest TEE when VMs are being created using Hyper-V.
+		//
+		// This leads us to check for the Hyper-V cpuid features
+		// (0x4000000C), and then for the `ebx` value set.
+		//
+		// For Intel TDX, `ebx` is set as `0xbe3`, being 3 the part
+		// we're mostly interested about,according to:
+		// https://github.com/torvalds/linux/blob/d2f51b3516dade79269ff45eae2a7668ae711b25/arch/x86/include/asm/hyperv-tlfs.h#L169-L174
+		_, ebx, _, _ := cpuid(0x4000000C)
+		fs.setIf(ebx == 0xbe3, TDX_GUEST)
+	}
+
 	if mfi >= 0x21 {
 		// Intel Trusted Domain Extensions Guests have their own cpuid leaf (0x21).
 		_, ebx, ecx, edx := cpuid(0x21)
@@ -1404,6 +1442,14 @@ func support() flagSet {
 	return fs
 }
 
+func (c *CPUInfo) supportAVX10() uint8 {
+	if c.maxFunc >= 0x24 && c.featureSet.inSet(AVX10) {
+		_, ebx, _, _ := cpuidex(0x24, 0)
+		return uint8(ebx)
+	}
+	return 0
+}
+
 func valAsString(values ...uint32) []byte {
 	r := make([]byte, 4*len(values))
 	for i, v := range values {
diff --git a/vendor/github.com/klauspost/cpuid/v2/detect_x86.go b/vendor/github.com/klauspost/cpuid/v2/detect_x86.go
index c946824ec0..c7dfa125de 100644
--- a/vendor/github.com/klauspost/cpuid/v2/detect_x86.go
+++ b/vendor/github.com/klauspost/cpuid/v2/detect_x86.go
@@ -31,6 +31,7 @@ func addInfo(c *CPUInfo, safe bool) {
 	c.LogicalCores = logicalCores()
 	c.PhysicalCores = physicalCores()
 	c.VendorID, c.VendorString = vendorID()
+	c.AVX10Level = c.supportAVX10()
 	c.cacheSize()
 	c.frequencies()
 }
diff --git a/vendor/github.com/klauspost/cpuid/v2/featureid_string.go b/vendor/github.com/klauspost/cpuid/v2/featureid_string.go
index 024c706af5..43bd05f516 100644
--- a/vendor/github.com/klauspost/cpuid/v2/featureid_string.go
+++ b/vendor/github.com/klauspost/cpuid/v2/featureid_string.go
@@ -16,210 +16,217 @@ func _() {
 	_ = x[AMXFP16-6]
 	_ = x[AMXINT8-7]
 	_ = x[AMXTILE-8]
-	_ = x[AVX-9]
-	_ = x[AVX2-10]
-	_ = x[AVX512BF16-11]
-	_ = x[AVX512BITALG-12]
-	_ = x[AVX512BW-13]
-	_ = x[AVX512CD-14]
-	_ = x[AVX512DQ-15]
-	_ = x[AVX512ER-16]
-	_ = x[AVX512F-17]
-	_ = x[AVX512FP16-18]
-	_ = x[AVX512IFMA-19]
-	_ = x[AVX512PF-20]
-	_ = x[AVX512VBMI-21]
-	_ = x[AVX512VBMI2-22]
-	_ = x[AVX512VL-23]
-	_ = x[AVX512VNNI-24]
-	_ = x[AVX512VP2INTERSECT-25]
-	_ = x[AVX512VPOPCNTDQ-26]
-	_ = x[AVXIFMA-27]
-	_ = x[AVXNECONVERT-28]
-	_ = x[AVXSLOW-29]
-	_ = x[AVXVNNI-30]
-	_ = x[AVXVNNIINT8-31]
-	_ = x[BHI_CTRL-32]
-	_ = x[BMI1-33]
-	_ = x[BMI2-34]
-	_ = x[CETIBT-35]
-	_ = x[CETSS-36]
-	_ = x[CLDEMOTE-37]
-	_ = x[CLMUL-38]
-	_ = x[CLZERO-39]
-	_ = x[CMOV-40]
-	_ = x[CMPCCXADD-41]
-	_ = x[CMPSB_SCADBS_SHORT-42]
-	_ = x[CMPXCHG8-43]
-	_ = x[CPBOOST-44]
-	_ = x[CPPC-45]
-	_ = x[CX16-46]
-	_ = x[EFER_LMSLE_UNS-47]
-	_ = x[ENQCMD-48]
-	_ = x[ERMS-49]
-	_ = x[F16C-50]
-	_ = x[FLUSH_L1D-51]
-	_ = x[FMA3-52]
-	_ = x[FMA4-53]
-	_ = x[FP128-54]
-	_ = x[FP256-55]
-	_ = x[FSRM-56]
-	_ = x[FXSR-57]
-	_ = x[FXSROPT-58]
-	_ = x[GFNI-59]
-	_ = x[HLE-60]
-	_ = x[HRESET-61]
-	_ = x[HTT-62]
-	_ = x[HWA-63]
-	_ = x[HYBRID_CPU-64]
-	_ = x[HYPERVISOR-65]
-	_ = x[IA32_ARCH_CAP-66]
-	_ = x[IA32_CORE_CAP-67]
-	_ = x[IBPB-68]
-	_ = x[IBRS-69]
-	_ = x[IBRS_PREFERRED-70]
-	_ = x[IBRS_PROVIDES_SMP-71]
-	_ = x[IBS-72]
-	_ = x[IBSBRNTRGT-73]
-	_ = x[IBSFETCHSAM-74]
-	_ = x[IBSFFV-75]
-	_ = x[IBSOPCNT-76]
-	_ = x[IBSOPCNTEXT-77]
-	_ = x[IBSOPSAM-78]
-	_ = x[IBSRDWROPCNT-79]
-	_ = x[IBSRIPINVALIDCHK-80]
-	_ = x[IBS_FETCH_CTLX-81]
-	_ = x[IBS_OPDATA4-82]
-	_ = x[IBS_OPFUSE-83]
-	_ = x[IBS_PREVENTHOST-84]
-	_ = x[IBS_ZEN4-85]
-	_ = x[IDPRED_CTRL-86]
-	_ = x[INT_WBINVD-87]
-	_ = x[INVLPGB-88]
-	_ = x[LAHF-89]
-	_ = x[LAM-90]
-	_ = x[LBRVIRT-91]
-	_ = x[LZCNT-92]
-	_ = x[MCAOVERFLOW-93]
-	_ = x[MCDT_NO-94]
-	_ = x[MCOMMIT-95]
-	_ = x[MD_CLEAR-96]
-	_ = x[MMX-97]
-	_ = x[MMXEXT-98]
-	_ = x[MOVBE-99]
-	_ = x[MOVDIR64B-100]
-	_ = x[MOVDIRI-101]
-	_ = x[MOVSB_ZL-102]
-	_ = x[MOVU-103]
-	_ = x[MPX-104]
-	_ = x[MSRIRC-105]
-	_ = x[MSRLIST-106]
-	_ = x[MSR_PAGEFLUSH-107]
-	_ = x[NRIPS-108]
-	_ = x[NX-109]
-	_ = x[OSXSAVE-110]
-	_ = x[PCONFIG-111]
-	_ = x[POPCNT-112]
-	_ = x[PPIN-113]
-	_ = x[PREFETCHI-114]
-	_ = x[PSFD-115]
-	_ = x[RDPRU-116]
-	_ = x[RDRAND-117]
-	_ = x[RDSEED-118]
-	_ = x[RDTSCP-119]
-	_ = x[RRSBA_CTRL-120]
-	_ = x[RTM-121]
-	_ = x[RTM_ALWAYS_ABORT-122]
-	_ = x[SERIALIZE-123]
-	_ = x[SEV-124]
-	_ = x[SEV_64BIT-125]
-	_ = x[SEV_ALTERNATIVE-126]
-	_ = x[SEV_DEBUGSWAP-127]
-	_ = x[SEV_ES-128]
-	_ = x[SEV_RESTRICTED-129]
-	_ = x[SEV_SNP-130]
-	_ = x[SGX-131]
-	_ = x[SGXLC-132]
-	_ = x[SHA-133]
-	_ = x[SME-134]
-	_ = x[SME_COHERENT-135]
-	_ = x[SPEC_CTRL_SSBD-136]
-	_ = x[SRBDS_CTRL-137]
-	_ = x[SSE-138]
-	_ = x[SSE2-139]
-	_ = x[SSE3-140]
-	_ = x[SSE4-141]
-	_ = x[SSE42-142]
-	_ = x[SSE4A-143]
-	_ = x[SSSE3-144]
-	_ = x[STIBP-145]
-	_ = x[STIBP_ALWAYSON-146]
-	_ = x[STOSB_SHORT-147]
-	_ = x[SUCCOR-148]
-	_ = x[SVM-149]
-	_ = x[SVMDA-150]
-	_ = x[SVMFBASID-151]
-	_ = x[SVML-152]
-	_ = x[SVMNP-153]
-	_ = x[SVMPF-154]
-	_ = x[SVMPFT-155]
-	_ = x[SYSCALL-156]
-	_ = x[SYSEE-157]
-	_ = x[TBM-158]
-	_ = x[TDX_GUEST-159]
-	_ = x[TLB_FLUSH_NESTED-160]
-	_ = x[TME-161]
-	_ = x[TOPEXT-162]
-	_ = x[TSCRATEMSR-163]
-	_ = x[TSXLDTRK-164]
-	_ = x[VAES-165]
-	_ = x[VMCBCLEAN-166]
-	_ = x[VMPL-167]
-	_ = x[VMSA_REGPROT-168]
-	_ = x[VMX-169]
-	_ = x[VPCLMULQDQ-170]
-	_ = x[VTE-171]
-	_ = x[WAITPKG-172]
-	_ = x[WBNOINVD-173]
-	_ = x[WRMSRNS-174]
-	_ = x[X87-175]
-	_ = x[XGETBV1-176]
-	_ = x[XOP-177]
-	_ = x[XSAVE-178]
-	_ = x[XSAVEC-179]
-	_ = x[XSAVEOPT-180]
-	_ = x[XSAVES-181]
-	_ = x[AESARM-182]
-	_ = x[ARMCPUID-183]
-	_ = x[ASIMD-184]
-	_ = x[ASIMDDP-185]
-	_ = x[ASIMDHP-186]
-	_ = x[ASIMDRDM-187]
-	_ = x[ATOMICS-188]
-	_ = x[CRC32-189]
-	_ = x[DCPOP-190]
-	_ = x[EVTSTRM-191]
-	_ = x[FCMA-192]
-	_ = x[FP-193]
-	_ = x[FPHP-194]
-	_ = x[GPA-195]
-	_ = x[JSCVT-196]
-	_ = x[LRCPC-197]
-	_ = x[PMULL-198]
-	_ = x[SHA1-199]
-	_ = x[SHA2-200]
-	_ = x[SHA3-201]
-	_ = x[SHA512-202]
-	_ = x[SM3-203]
-	_ = x[SM4-204]
-	_ = x[SVE-205]
-	_ = x[lastID-206]
+	_ = x[APX_F-9]
+	_ = x[AVX-10]
+	_ = x[AVX10-11]
+	_ = x[AVX10_128-12]
+	_ = x[AVX10_256-13]
+	_ = x[AVX10_512-14]
+	_ = x[AVX2-15]
+	_ = x[AVX512BF16-16]
+	_ = x[AVX512BITALG-17]
+	_ = x[AVX512BW-18]
+	_ = x[AVX512CD-19]
+	_ = x[AVX512DQ-20]
+	_ = x[AVX512ER-21]
+	_ = x[AVX512F-22]
+	_ = x[AVX512FP16-23]
+	_ = x[AVX512IFMA-24]
+	_ = x[AVX512PF-25]
+	_ = x[AVX512VBMI-26]
+	_ = x[AVX512VBMI2-27]
+	_ = x[AVX512VL-28]
+	_ = x[AVX512VNNI-29]
+	_ = x[AVX512VP2INTERSECT-30]
+	_ = x[AVX512VPOPCNTDQ-31]
+	_ = x[AVXIFMA-32]
+	_ = x[AVXNECONVERT-33]
+	_ = x[AVXSLOW-34]
+	_ = x[AVXVNNI-35]
+	_ = x[AVXVNNIINT8-36]
+	_ = x[BHI_CTRL-37]
+	_ = x[BMI1-38]
+	_ = x[BMI2-39]
+	_ = x[CETIBT-40]
+	_ = x[CETSS-41]
+	_ = x[CLDEMOTE-42]
+	_ = x[CLMUL-43]
+	_ = x[CLZERO-44]
+	_ = x[CMOV-45]
+	_ = x[CMPCCXADD-46]
+	_ = x[CMPSB_SCADBS_SHORT-47]
+	_ = x[CMPXCHG8-48]
+	_ = x[CPBOOST-49]
+	_ = x[CPPC-50]
+	_ = x[CX16-51]
+	_ = x[EFER_LMSLE_UNS-52]
+	_ = x[ENQCMD-53]
+	_ = x[ERMS-54]
+	_ = x[F16C-55]
+	_ = x[FLUSH_L1D-56]
+	_ = x[FMA3-57]
+	_ = x[FMA4-58]
+	_ = x[FP128-59]
+	_ = x[FP256-60]
+	_ = x[FSRM-61]
+	_ = x[FXSR-62]
+	_ = x[FXSROPT-63]
+	_ = x[GFNI-64]
+	_ = x[HLE-65]
+	_ = x[HRESET-66]
+	_ = x[HTT-67]
+	_ = x[HWA-68]
+	_ = x[HYBRID_CPU-69]
+	_ = x[HYPERVISOR-70]
+	_ = x[IA32_ARCH_CAP-71]
+	_ = x[IA32_CORE_CAP-72]
+	_ = x[IBPB-73]
+	_ = x[IBRS-74]
+	_ = x[IBRS_PREFERRED-75]
+	_ = x[IBRS_PROVIDES_SMP-76]
+	_ = x[IBS-77]
+	_ = x[IBSBRNTRGT-78]
+	_ = x[IBSFETCHSAM-79]
+	_ = x[IBSFFV-80]
+	_ = x[IBSOPCNT-81]
+	_ = x[IBSOPCNTEXT-82]
+	_ = x[IBSOPSAM-83]
+	_ = x[IBSRDWROPCNT-84]
+	_ = x[IBSRIPINVALIDCHK-85]
+	_ = x[IBS_FETCH_CTLX-86]
+	_ = x[IBS_OPDATA4-87]
+	_ = x[IBS_OPFUSE-88]
+	_ = x[IBS_PREVENTHOST-89]
+	_ = x[IBS_ZEN4-90]
+	_ = x[IDPRED_CTRL-91]
+	_ = x[INT_WBINVD-92]
+	_ = x[INVLPGB-93]
+	_ = x[KEYLOCKER-94]
+	_ = x[KEYLOCKERW-95]
+	_ = x[LAHF-96]
+	_ = x[LAM-97]
+	_ = x[LBRVIRT-98]
+	_ = x[LZCNT-99]
+	_ = x[MCAOVERFLOW-100]
+	_ = x[MCDT_NO-101]
+	_ = x[MCOMMIT-102]
+	_ = x[MD_CLEAR-103]
+	_ = x[MMX-104]
+	_ = x[MMXEXT-105]
+	_ = x[MOVBE-106]
+	_ = x[MOVDIR64B-107]
+	_ = x[MOVDIRI-108]
+	_ = x[MOVSB_ZL-109]
+	_ = x[MOVU-110]
+	_ = x[MPX-111]
+	_ = x[MSRIRC-112]
+	_ = x[MSRLIST-113]
+	_ = x[MSR_PAGEFLUSH-114]
+	_ = x[NRIPS-115]
+	_ = x[NX-116]
+	_ = x[OSXSAVE-117]
+	_ = x[PCONFIG-118]
+	_ = x[POPCNT-119]
+	_ = x[PPIN-120]
+	_ = x[PREFETCHI-121]
+	_ = x[PSFD-122]
+	_ = x[RDPRU-123]
+	_ = x[RDRAND-124]
+	_ = x[RDSEED-125]
+	_ = x[RDTSCP-126]
+	_ = x[RRSBA_CTRL-127]
+	_ = x[RTM-128]
+	_ = x[RTM_ALWAYS_ABORT-129]
+	_ = x[SERIALIZE-130]
+	_ = x[SEV-131]
+	_ = x[SEV_64BIT-132]
+	_ = x[SEV_ALTERNATIVE-133]
+	_ = x[SEV_DEBUGSWAP-134]
+	_ = x[SEV_ES-135]
+	_ = x[SEV_RESTRICTED-136]
+	_ = x[SEV_SNP-137]
+	_ = x[SGX-138]
+	_ = x[SGXLC-139]
+	_ = x[SHA-140]
+	_ = x[SME-141]
+	_ = x[SME_COHERENT-142]
+	_ = x[SPEC_CTRL_SSBD-143]
+	_ = x[SRBDS_CTRL-144]
+	_ = x[SSE-145]
+	_ = x[SSE2-146]
+	_ = x[SSE3-147]
+	_ = x[SSE4-148]
+	_ = x[SSE42-149]
+	_ = x[SSE4A-150]
+	_ = x[SSSE3-151]
+	_ = x[STIBP-152]
+	_ = x[STIBP_ALWAYSON-153]
+	_ = x[STOSB_SHORT-154]
+	_ = x[SUCCOR-155]
+	_ = x[SVM-156]
+	_ = x[SVMDA-157]
+	_ = x[SVMFBASID-158]
+	_ = x[SVML-159]
+	_ = x[SVMNP-160]
+	_ = x[SVMPF-161]
+	_ = x[SVMPFT-162]
+	_ = x[SYSCALL-163]
+	_ = x[SYSEE-164]
+	_ = x[TBM-165]
+	_ = x[TDX_GUEST-166]
+	_ = x[TLB_FLUSH_NESTED-167]
+	_ = x[TME-168]
+	_ = x[TOPEXT-169]
+	_ = x[TSCRATEMSR-170]
+	_ = x[TSXLDTRK-171]
+	_ = x[VAES-172]
+	_ = x[VMCBCLEAN-173]
+	_ = x[VMPL-174]
+	_ = x[VMSA_REGPROT-175]
+	_ = x[VMX-176]
+	_ = x[VPCLMULQDQ-177]
+	_ = x[VTE-178]
+	_ = x[WAITPKG-179]
+	_ = x[WBNOINVD-180]
+	_ = x[WRMSRNS-181]
+	_ = x[X87-182]
+	_ = x[XGETBV1-183]
+	_ = x[XOP-184]
+	_ = x[XSAVE-185]
+	_ = x[XSAVEC-186]
+	_ = x[XSAVEOPT-187]
+	_ = x[XSAVES-188]
+	_ = x[AESARM-189]
+	_ = x[ARMCPUID-190]
+	_ = x[ASIMD-191]
+	_ = x[ASIMDDP-192]
+	_ = x[ASIMDHP-193]
+	_ = x[ASIMDRDM-194]
+	_ = x[ATOMICS-195]
+	_ = x[CRC32-196]
+	_ = x[DCPOP-197]
+	_ = x[EVTSTRM-198]
+	_ = x[FCMA-199]
+	_ = x[FP-200]
+	_ = x[FPHP-201]
+	_ = x[GPA-202]
+	_ = x[JSCVT-203]
+	_ = x[LRCPC-204]
+	_ = x[PMULL-205]
+	_ = x[SHA1-206]
+	_ = x[SHA2-207]
+	_ = x[SHA3-208]
+	_ = x[SHA512-209]
+	_ = x[SM3-210]
+	_ = x[SM4-211]
+	_ = x[SVE-212]
+	_ = x[lastID-213]
 	_ = x[firstID-0]
 }
 
-const _FeatureID_name = "firstIDADXAESNIAMD3DNOWAMD3DNOWEXTAMXBF16AMXFP16AMXINT8AMXTILEAVXAVX2AVX512BF16AVX512BITALGAVX512BWAVX512CDAVX512DQAVX512ERAVX512FAVX512FP16AVX512IFMAAVX512PFAVX512VBMIAVX512VBMI2AVX512VLAVX512VNNIAVX512VP2INTERSECTAVX512VPOPCNTDQAVXIFMAAVXNECONVERTAVXSLOWAVXVNNIAVXVNNIINT8BHI_CTRLBMI1BMI2CETIBTCETSSCLDEMOTECLMULCLZEROCMOVCMPCCXADDCMPSB_SCADBS_SHORTCMPXCHG8CPBOOSTCPPCCX16EFER_LMSLE_UNSENQCMDERMSF16CFLUSH_L1DFMA3FMA4FP128FP256FSRMFXSRFXSROPTGFNIHLEHRESETHTTHWAHYBRID_CPUHYPERVISORIA32_ARCH_CAPIA32_CORE_CAPIBPBIBRSIBRS_PREFERREDIBRS_PROVIDES_SMPIBSIBSBRNTRGTIBSFETCHSAMIBSFFVIBSOPCNTIBSOPCNTEXTIBSOPSAMIBSRDWROPCNTIBSRIPINVALIDCHKIBS_FETCH_CTLXIBS_OPDATA4IBS_OPFUSEIBS_PREVENTHOSTIBS_ZEN4IDPRED_CTRLINT_WBINVDINVLPGBLAHFLAMLBRVIRTLZCNTMCAOVERFLOWMCDT_NOMCOMMITMD_CLEARMMXMMXEXTMOVBEMOVDIR64BMOVDIRIMOVSB_ZLMOVUMPXMSRIRCMSRLISTMSR_PAGEFLUSHNRIPSNXOSXSAVEPCONFIGPOPCNTPPINPREFETCHIPSFDRDPRURDRANDRDSEEDRDTSCPRRSBA_CTRLRTMRTM_ALWAYS_ABORTSERIALIZESEVSEV_64BITSEV_ALTERNATIVESEV_DEBUGSWAPSEV_ESSEV_RESTRICTEDSEV_SNPSGXSGXLCSHASMESME_COHERENTSPEC_CTRL_SSBDSRBDS_CTRLSSESSE2SSE3SSE4SSE42SSE4ASSSE3STIBPSTIBP_ALWAYSONSTOSB_SHORTSUCCORSVMSVMDASVMFBASIDSVMLSVMNPSVMPFSVMPFTSYSCALLSYSEETBMTDX_GUESTTLB_FLUSH_NESTEDTMETOPEXTTSCRATEMSRTSXLDTRKVAESVMCBCLEANVMPLVMSA_REGPROTVMXVPCLMULQDQVTEWAITPKGWBNOINVDWRMSRNSX87XGETBV1XOPXSAVEXSAVECXSAVEOPTXSAVESAESARMARMCPUIDASIMDASIMDDPASIMDHPASIMDRDMATOMICSCRC32DCPOPEVTSTRMFCMAFPFPHPGPAJSCVTLRCPCPMULLSHA1SHA2SHA3SHA512SM3SM4SVElastID"
+const _FeatureID_name = "firstIDADXAESNIAMD3DNOWAMD3DNOWEXTAMXBF16AMXFP16AMXINT8AMXTILEAPX_FAVXAVX10AVX10_128AVX10_256AVX10_512AVX2AVX512BF16AVX512BITALGAVX512BWAVX512CDAVX512DQAVX512ERAVX512FAVX512FP16AVX512IFMAAVX512PFAVX512VBMIAVX512VBMI2AVX512VLAVX512VNNIAVX512VP2INTERSECTAVX512VPOPCNTDQAVXIFMAAVXNECONVERTAVXSLOWAVXVNNIAVXVNNIINT8BHI_CTRLBMI1BMI2CETIBTCETSSCLDEMOTECLMULCLZEROCMOVCMPCCXADDCMPSB_SCADBS_SHORTCMPXCHG8CPBOOSTCPPCCX16EFER_LMSLE_UNSENQCMDERMSF16CFLUSH_L1DFMA3FMA4FP128FP256FSRMFXSRFXSROPTGFNIHLEHRESETHTTHWAHYBRID_CPUHYPERVISORIA32_ARCH_CAPIA32_CORE_CAPIBPBIBRSIBRS_PREFERREDIBRS_PROVIDES_SMPIBSIBSBRNTRGTIBSFETCHSAMIBSFFVIBSOPCNTIBSOPCNTEXTIBSOPSAMIBSRDWROPCNTIBSRIPINVALIDCHKIBS_FETCH_CTLXIBS_OPDATA4IBS_OPFUSEIBS_PREVENTHOSTIBS_ZEN4IDPRED_CTRLINT_WBINVDINVLPGBKEYLOCKERKEYLOCKERWLAHFLAMLBRVIRTLZCNTMCAOVERFLOWMCDT_NOMCOMMITMD_CLEARMMXMMXEXTMOVBEMOVDIR64BMOVDIRIMOVSB_ZLMOVUMPXMSRIRCMSRLISTMSR_PAGEFLUSHNRIPSNXOSXSAVEPCONFIGPOPCNTPPINPREFETCHIPSFDRDPRURDRANDRDSEEDRDTSCPRRSBA_CTRLRTMRTM_ALWAYS_ABORTSERIALIZESEVSEV_64BITSEV_ALTERNATIVESEV_DEBUGSWAPSEV_ESSEV_RESTRICTEDSEV_SNPSGXSGXLCSHASMESME_COHERENTSPEC_CTRL_SSBDSRBDS_CTRLSSESSE2SSE3SSE4SSE42SSE4ASSSE3STIBPSTIBP_ALWAYSONSTOSB_SHORTSUCCORSVMSVMDASVMFBASIDSVMLSVMNPSVMPFSVMPFTSYSCALLSYSEETBMTDX_GUESTTLB_FLUSH_NESTEDTMETOPEXTTSCRATEMSRTSXLDTRKVAESVMCBCLEANVMPLVMSA_REGPROTVMXVPCLMULQDQVTEWAITPKGWBNOINVDWRMSRNSX87XGETBV1XOPXSAVEXSAVECXSAVEOPTXSAVESAESARMARMCPUIDASIMDASIMDDPASIMDHPASIMDRDMATOMICSCRC32DCPOPEVTSTRMFCMAFPFPHPGPAJSCVTLRCPCPMULLSHA1SHA2SHA3SHA512SM3SM4SVElastID"
 
-var _FeatureID_index = [...]uint16{0, 7, 10, 15, 23, 34, 41, 48, 55, 62, 65, 69, 79, 91, 99, 107, 115, 123, 130, 140, 150, 158, 168, 179, 187, 197, 215, 230, 237, 249, 256, 263, 274, 282, 286, 290, 296, 301, 309, 314, 320, 324, 333, 351, 359, 366, 370, 374, 388, 394, 398, 402, 411, 415, 419, 424, 429, 433, 437, 444, 448, 451, 457, 460, 463, 473, 483, 496, 509, 513, 517, 531, 548, 551, 561, 572, 578, 586, 597, 605, 617, 633, 647, 658, 668, 683, 691, 702, 712, 719, 723, 726, 733, 738, 749, 756, 763, 771, 774, 780, 785, 794, 801, 809, 813, 816, 822, 829, 842, 847, 849, 856, 863, 869, 873, 882, 886, 891, 897, 903, 909, 919, 922, 938, 947, 950, 959, 974, 987, 993, 1007, 1014, 1017, 1022, 1025, 1028, 1040, 1054, 1064, 1067, 1071, 1075, 1079, 1084, 1089, 1094, 1099, 1113, 1124, 1130, 1133, 1138, 1147, 1151, 1156, 1161, 1167, 1174, 1179, 1182, 1191, 1207, 1210, 1216, 1226, 1234, 1238, 1247, 1251, 1263, 1266, 1276, 1279, 1286, 1294, 1301, 1304, 1311, 1314, 1319, 1325, 1333, 1339, 1345, 1353, 1358, 1365, 1372, 1380, 1387, 1392, 1397, 1404, 1408, 1410, 1414, 1417, 1422, 1427, 1432, 1436, 1440, 1444, 1450, 1453, 1456, 1459, 1465}
+var _FeatureID_index = [...]uint16{0, 7, 10, 15, 23, 34, 41, 48, 55, 62, 67, 70, 75, 84, 93, 102, 106, 116, 128, 136, 144, 152, 160, 167, 177, 187, 195, 205, 216, 224, 234, 252, 267, 274, 286, 293, 300, 311, 319, 323, 327, 333, 338, 346, 351, 357, 361, 370, 388, 396, 403, 407, 411, 425, 431, 435, 439, 448, 452, 456, 461, 466, 470, 474, 481, 485, 488, 494, 497, 500, 510, 520, 533, 546, 550, 554, 568, 585, 588, 598, 609, 615, 623, 634, 642, 654, 670, 684, 695, 705, 720, 728, 739, 749, 756, 765, 775, 779, 782, 789, 794, 805, 812, 819, 827, 830, 836, 841, 850, 857, 865, 869, 872, 878, 885, 898, 903, 905, 912, 919, 925, 929, 938, 942, 947, 953, 959, 965, 975, 978, 994, 1003, 1006, 1015, 1030, 1043, 1049, 1063, 1070, 1073, 1078, 1081, 1084, 1096, 1110, 1120, 1123, 1127, 1131, 1135, 1140, 1145, 1150, 1155, 1169, 1180, 1186, 1189, 1194, 1203, 1207, 1212, 1217, 1223, 1230, 1235, 1238, 1247, 1263, 1266, 1272, 1282, 1290, 1294, 1303, 1307, 1319, 1322, 1332, 1335, 1342, 1350, 1357, 1360, 1367, 1370, 1375, 1381, 1389, 1395, 1401, 1409, 1414, 1421, 1428, 1436, 1443, 1448, 1453, 1460, 1464, 1466, 1470, 1473, 1478, 1483, 1488, 1492, 1496, 1500, 1506, 1509, 1512, 1515, 1521}
 
 func (i FeatureID) String() string {
 	if i < 0 || i >= FeatureID(len(_FeatureID_index)-1) {
diff --git a/vendor/github.com/mattn/go-colorable/LICENSE b/vendor/github.com/mattn/go-colorable/LICENSE
new file mode 100644
index 0000000000..91b5cef30e
--- /dev/null
+++ b/vendor/github.com/mattn/go-colorable/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2016 Yasuhiro Matsumoto
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/vendor/github.com/mattn/go-colorable/README.md b/vendor/github.com/mattn/go-colorable/README.md
new file mode 100644
index 0000000000..ca0483711c
--- /dev/null
+++ b/vendor/github.com/mattn/go-colorable/README.md
@@ -0,0 +1,48 @@
+# go-colorable
+
+[![Build Status](https://github.com/mattn/go-colorable/workflows/test/badge.svg)](https://github.com/mattn/go-colorable/actions?query=workflow%3Atest)
+[![Codecov](https://codecov.io/gh/mattn/go-colorable/branch/master/graph/badge.svg)](https://codecov.io/gh/mattn/go-colorable)
+[![GoDoc](https://godoc.org/github.com/mattn/go-colorable?status.svg)](http://godoc.org/github.com/mattn/go-colorable)
+[![Go Report Card](https://goreportcard.com/badge/mattn/go-colorable)](https://goreportcard.com/report/mattn/go-colorable)
+
+Colorable writer for windows.
+
+For example, most of logger packages doesn't show colors on windows. (I know we can do it with ansicon. But I don't want.)
+This package is possible to handle escape sequence for ansi color on windows.
+
+## Too Bad!
+
+![](https://raw.githubusercontent.com/mattn/go-colorable/gh-pages/bad.png)
+
+
+## So Good!
+
+![](https://raw.githubusercontent.com/mattn/go-colorable/gh-pages/good.png)
+
+## Usage
+
+```go
+logrus.SetFormatter(&logrus.TextFormatter{ForceColors: true})
+logrus.SetOutput(colorable.NewColorableStdout())
+
+logrus.Info("succeeded")
+logrus.Warn("not correct")
+logrus.Error("something error")
+logrus.Fatal("panic")
+```
+
+You can compile above code on non-windows OSs.
+
+## Installation
+
+```
+$ go get github.com/mattn/go-colorable
+```
+
+# License
+
+MIT
+
+# Author
+
+Yasuhiro Matsumoto (a.k.a mattn)
diff --git a/vendor/github.com/mattn/go-colorable/colorable_appengine.go b/vendor/github.com/mattn/go-colorable/colorable_appengine.go
new file mode 100644
index 0000000000..416d1bbbf8
--- /dev/null
+++ b/vendor/github.com/mattn/go-colorable/colorable_appengine.go
@@ -0,0 +1,38 @@
+//go:build appengine
+// +build appengine
+
+package colorable
+
+import (
+	"io"
+	"os"
+
+	_ "github.com/mattn/go-isatty"
+)
+
+// NewColorable returns new instance of Writer which handles escape sequence.
+func NewColorable(file *os.File) io.Writer {
+	if file == nil {
+		panic("nil passed instead of *os.File to NewColorable()")
+	}
+
+	return file
+}
+
+// NewColorableStdout returns new instance of Writer which handles escape sequence for stdout.
+func NewColorableStdout() io.Writer {
+	return os.Stdout
+}
+
+// NewColorableStderr returns new instance of Writer which handles escape sequence for stderr.
+func NewColorableStderr() io.Writer {
+	return os.Stderr
+}
+
+// EnableColorsStdout enable colors if possible.
+func EnableColorsStdout(enabled *bool) func() {
+	if enabled != nil {
+		*enabled = true
+	}
+	return func() {}
+}
diff --git a/vendor/github.com/mattn/go-colorable/colorable_others.go b/vendor/github.com/mattn/go-colorable/colorable_others.go
new file mode 100644
index 0000000000..766d94603a
--- /dev/null
+++ b/vendor/github.com/mattn/go-colorable/colorable_others.go
@@ -0,0 +1,38 @@
+//go:build !windows && !appengine
+// +build !windows,!appengine
+
+package colorable
+
+import (
+	"io"
+	"os"
+
+	_ "github.com/mattn/go-isatty"
+)
+
+// NewColorable returns new instance of Writer which handles escape sequence.
+func NewColorable(file *os.File) io.Writer {
+	if file == nil {
+		panic("nil passed instead of *os.File to NewColorable()")
+	}
+
+	return file
+}
+
+// NewColorableStdout returns new instance of Writer which handles escape sequence for stdout.
+func NewColorableStdout() io.Writer {
+	return os.Stdout
+}
+
+// NewColorableStderr returns new instance of Writer which handles escape sequence for stderr.
+func NewColorableStderr() io.Writer {
+	return os.Stderr
+}
+
+// EnableColorsStdout enable colors if possible.
+func EnableColorsStdout(enabled *bool) func() {
+	if enabled != nil {
+		*enabled = true
+	}
+	return func() {}
+}
diff --git a/vendor/github.com/mattn/go-colorable/colorable_windows.go b/vendor/github.com/mattn/go-colorable/colorable_windows.go
new file mode 100644
index 0000000000..1846ad5ab4
--- /dev/null
+++ b/vendor/github.com/mattn/go-colorable/colorable_windows.go
@@ -0,0 +1,1047 @@
+//go:build windows && !appengine
+// +build windows,!appengine
+
+package colorable
+
+import (
+	"bytes"
+	"io"
+	"math"
+	"os"
+	"strconv"
+	"strings"
+	"sync"
+	"syscall"
+	"unsafe"
+
+	"github.com/mattn/go-isatty"
+)
+
+const (
+	foregroundBlue      = 0x1
+	foregroundGreen     = 0x2
+	foregroundRed       = 0x4
+	foregroundIntensity = 0x8
+	foregroundMask      = (foregroundRed | foregroundBlue | foregroundGreen | foregroundIntensity)
+	backgroundBlue      = 0x10
+	backgroundGreen     = 0x20
+	backgroundRed       = 0x40
+	backgroundIntensity = 0x80
+	backgroundMask      = (backgroundRed | backgroundBlue | backgroundGreen | backgroundIntensity)
+	commonLvbUnderscore = 0x8000
+
+	cENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x4
+)
+
+const (
+	genericRead  = 0x80000000
+	genericWrite = 0x40000000
+)
+
+const (
+	consoleTextmodeBuffer = 0x1
+)
+
+type wchar uint16
+type short int16
+type dword uint32
+type word uint16
+
+type coord struct {
+	x short
+	y short
+}
+
+type smallRect struct {
+	left   short
+	top    short
+	right  short
+	bottom short
+}
+
+type consoleScreenBufferInfo struct {
+	size              coord
+	cursorPosition    coord
+	attributes        word
+	window            smallRect
+	maximumWindowSize coord
+}
+
+type consoleCursorInfo struct {
+	size    dword
+	visible int32
+}
+
+var (
+	kernel32                       = syscall.NewLazyDLL("kernel32.dll")
+	procGetConsoleScreenBufferInfo = kernel32.NewProc("GetConsoleScreenBufferInfo")
+	procSetConsoleTextAttribute    = kernel32.NewProc("SetConsoleTextAttribute")
+	procSetConsoleCursorPosition   = kernel32.NewProc("SetConsoleCursorPosition")
+	procFillConsoleOutputCharacter = kernel32.NewProc("FillConsoleOutputCharacterW")
+	procFillConsoleOutputAttribute = kernel32.NewProc("FillConsoleOutputAttribute")
+	procGetConsoleCursorInfo       = kernel32.NewProc("GetConsoleCursorInfo")
+	procSetConsoleCursorInfo       = kernel32.NewProc("SetConsoleCursorInfo")
+	procSetConsoleTitle            = kernel32.NewProc("SetConsoleTitleW")
+	procGetConsoleMode             = kernel32.NewProc("GetConsoleMode")
+	procSetConsoleMode             = kernel32.NewProc("SetConsoleMode")
+	procCreateConsoleScreenBuffer  = kernel32.NewProc("CreateConsoleScreenBuffer")
+)
+
+// Writer provides colorable Writer to the console
+type Writer struct {
+	out       io.Writer
+	handle    syscall.Handle
+	althandle syscall.Handle
+	oldattr   word
+	oldpos    coord
+	rest      bytes.Buffer
+	mutex     sync.Mutex
+}
+
+// NewColorable returns new instance of Writer which handles escape sequence from File.
+func NewColorable(file *os.File) io.Writer {
+	if file == nil {
+		panic("nil passed instead of *os.File to NewColorable()")
+	}
+
+	if isatty.IsTerminal(file.Fd()) {
+		var mode uint32
+		if r, _, _ := procGetConsoleMode.Call(file.Fd(), uintptr(unsafe.Pointer(&mode))); r != 0 && mode&cENABLE_VIRTUAL_TERMINAL_PROCESSING != 0 {
+			return file
+		}
+		var csbi consoleScreenBufferInfo
+		handle := syscall.Handle(file.Fd())
+		procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
+		return &Writer{out: file, handle: handle, oldattr: csbi.attributes, oldpos: coord{0, 0}}
+	}
+	return file
+}
+
+// NewColorableStdout returns new instance of Writer which handles escape sequence for stdout.
+func NewColorableStdout() io.Writer {
+	return NewColorable(os.Stdout)
+}
+
+// NewColorableStderr returns new instance of Writer which handles escape sequence for stderr.
+func NewColorableStderr() io.Writer {
+	return NewColorable(os.Stderr)
+}
+
+var color256 = map[int]int{
+	0:   0x000000,
+	1:   0x800000,
+	2:   0x008000,
+	3:   0x808000,
+	4:   0x000080,
+	5:   0x800080,
+	6:   0x008080,
+	7:   0xc0c0c0,
+	8:   0x808080,
+	9:   0xff0000,
+	10:  0x00ff00,
+	11:  0xffff00,
+	12:  0x0000ff,
+	13:  0xff00ff,
+	14:  0x00ffff,
+	15:  0xffffff,
+	16:  0x000000,
+	17:  0x00005f,
+	18:  0x000087,
+	19:  0x0000af,
+	20:  0x0000d7,
+	21:  0x0000ff,
+	22:  0x005f00,
+	23:  0x005f5f,
+	24:  0x005f87,
+	25:  0x005faf,
+	26:  0x005fd7,
+	27:  0x005fff,
+	28:  0x008700,
+	29:  0x00875f,
+	30:  0x008787,
+	31:  0x0087af,
+	32:  0x0087d7,
+	33:  0x0087ff,
+	34:  0x00af00,
+	35:  0x00af5f,
+	36:  0x00af87,
+	37:  0x00afaf,
+	38:  0x00afd7,
+	39:  0x00afff,
+	40:  0x00d700,
+	41:  0x00d75f,
+	42:  0x00d787,
+	43:  0x00d7af,
+	44:  0x00d7d7,
+	45:  0x00d7ff,
+	46:  0x00ff00,
+	47:  0x00ff5f,
+	48:  0x00ff87,
+	49:  0x00ffaf,
+	50:  0x00ffd7,
+	51:  0x00ffff,
+	52:  0x5f0000,
+	53:  0x5f005f,
+	54:  0x5f0087,
+	55:  0x5f00af,
+	56:  0x5f00d7,
+	57:  0x5f00ff,
+	58:  0x5f5f00,
+	59:  0x5f5f5f,
+	60:  0x5f5f87,
+	61:  0x5f5faf,
+	62:  0x5f5fd7,
+	63:  0x5f5fff,
+	64:  0x5f8700,
+	65:  0x5f875f,
+	66:  0x5f8787,
+	67:  0x5f87af,
+	68:  0x5f87d7,
+	69:  0x5f87ff,
+	70:  0x5faf00,
+	71:  0x5faf5f,
+	72:  0x5faf87,
+	73:  0x5fafaf,
+	74:  0x5fafd7,
+	75:  0x5fafff,
+	76:  0x5fd700,
+	77:  0x5fd75f,
+	78:  0x5fd787,
+	79:  0x5fd7af,
+	80:  0x5fd7d7,
+	81:  0x5fd7ff,
+	82:  0x5fff00,
+	83:  0x5fff5f,
+	84:  0x5fff87,
+	85:  0x5fffaf,
+	86:  0x5fffd7,
+	87:  0x5fffff,
+	88:  0x870000,
+	89:  0x87005f,
+	90:  0x870087,
+	91:  0x8700af,
+	92:  0x8700d7,
+	93:  0x8700ff,
+	94:  0x875f00,
+	95:  0x875f5f,
+	96:  0x875f87,
+	97:  0x875faf,
+	98:  0x875fd7,
+	99:  0x875fff,
+	100: 0x878700,
+	101: 0x87875f,
+	102: 0x878787,
+	103: 0x8787af,
+	104: 0x8787d7,
+	105: 0x8787ff,
+	106: 0x87af00,
+	107: 0x87af5f,
+	108: 0x87af87,
+	109: 0x87afaf,
+	110: 0x87afd7,
+	111: 0x87afff,
+	112: 0x87d700,
+	113: 0x87d75f,
+	114: 0x87d787,
+	115: 0x87d7af,
+	116: 0x87d7d7,
+	117: 0x87d7ff,
+	118: 0x87ff00,
+	119: 0x87ff5f,
+	120: 0x87ff87,
+	121: 0x87ffaf,
+	122: 0x87ffd7,
+	123: 0x87ffff,
+	124: 0xaf0000,
+	125: 0xaf005f,
+	126: 0xaf0087,
+	127: 0xaf00af,
+	128: 0xaf00d7,
+	129: 0xaf00ff,
+	130: 0xaf5f00,
+	131: 0xaf5f5f,
+	132: 0xaf5f87,
+	133: 0xaf5faf,
+	134: 0xaf5fd7,
+	135: 0xaf5fff,
+	136: 0xaf8700,
+	137: 0xaf875f,
+	138: 0xaf8787,
+	139: 0xaf87af,
+	140: 0xaf87d7,
+	141: 0xaf87ff,
+	142: 0xafaf00,
+	143: 0xafaf5f,
+	144: 0xafaf87,
+	145: 0xafafaf,
+	146: 0xafafd7,
+	147: 0xafafff,
+	148: 0xafd700,
+	149: 0xafd75f,
+	150: 0xafd787,
+	151: 0xafd7af,
+	152: 0xafd7d7,
+	153: 0xafd7ff,
+	154: 0xafff00,
+	155: 0xafff5f,
+	156: 0xafff87,
+	157: 0xafffaf,
+	158: 0xafffd7,
+	159: 0xafffff,
+	160: 0xd70000,
+	161: 0xd7005f,
+	162: 0xd70087,
+	163: 0xd700af,
+	164: 0xd700d7,
+	165: 0xd700ff,
+	166: 0xd75f00,
+	167: 0xd75f5f,
+	168: 0xd75f87,
+	169: 0xd75faf,
+	170: 0xd75fd7,
+	171: 0xd75fff,
+	172: 0xd78700,
+	173: 0xd7875f,
+	174: 0xd78787,
+	175: 0xd787af,
+	176: 0xd787d7,
+	177: 0xd787ff,
+	178: 0xd7af00,
+	179: 0xd7af5f,
+	180: 0xd7af87,
+	181: 0xd7afaf,
+	182: 0xd7afd7,
+	183: 0xd7afff,
+	184: 0xd7d700,
+	185: 0xd7d75f,
+	186: 0xd7d787,
+	187: 0xd7d7af,
+	188: 0xd7d7d7,
+	189: 0xd7d7ff,
+	190: 0xd7ff00,
+	191: 0xd7ff5f,
+	192: 0xd7ff87,
+	193: 0xd7ffaf,
+	194: 0xd7ffd7,
+	195: 0xd7ffff,
+	196: 0xff0000,
+	197: 0xff005f,
+	198: 0xff0087,
+	199: 0xff00af,
+	200: 0xff00d7,
+	201: 0xff00ff,
+	202: 0xff5f00,
+	203: 0xff5f5f,
+	204: 0xff5f87,
+	205: 0xff5faf,
+	206: 0xff5fd7,
+	207: 0xff5fff,
+	208: 0xff8700,
+	209: 0xff875f,
+	210: 0xff8787,
+	211: 0xff87af,
+	212: 0xff87d7,
+	213: 0xff87ff,
+	214: 0xffaf00,
+	215: 0xffaf5f,
+	216: 0xffaf87,
+	217: 0xffafaf,
+	218: 0xffafd7,
+	219: 0xffafff,
+	220: 0xffd700,
+	221: 0xffd75f,
+	222: 0xffd787,
+	223: 0xffd7af,
+	224: 0xffd7d7,
+	225: 0xffd7ff,
+	226: 0xffff00,
+	227: 0xffff5f,
+	228: 0xffff87,
+	229: 0xffffaf,
+	230: 0xffffd7,
+	231: 0xffffff,
+	232: 0x080808,
+	233: 0x121212,
+	234: 0x1c1c1c,
+	235: 0x262626,
+	236: 0x303030,
+	237: 0x3a3a3a,
+	238: 0x444444,
+	239: 0x4e4e4e,
+	240: 0x585858,
+	241: 0x626262,
+	242: 0x6c6c6c,
+	243: 0x767676,
+	244: 0x808080,
+	245: 0x8a8a8a,
+	246: 0x949494,
+	247: 0x9e9e9e,
+	248: 0xa8a8a8,
+	249: 0xb2b2b2,
+	250: 0xbcbcbc,
+	251: 0xc6c6c6,
+	252: 0xd0d0d0,
+	253: 0xdadada,
+	254: 0xe4e4e4,
+	255: 0xeeeeee,
+}
+
+// `\033]0;TITLESTR\007`
+func doTitleSequence(er *bytes.Reader) error {
+	var c byte
+	var err error
+
+	c, err = er.ReadByte()
+	if err != nil {
+		return err
+	}
+	if c != '0' && c != '2' {
+		return nil
+	}
+	c, err = er.ReadByte()
+	if err != nil {
+		return err
+	}
+	if c != ';' {
+		return nil
+	}
+	title := make([]byte, 0, 80)
+	for {
+		c, err = er.ReadByte()
+		if err != nil {
+			return err
+		}
+		if c == 0x07 || c == '\n' {
+			break
+		}
+		title = append(title, c)
+	}
+	if len(title) > 0 {
+		title8, err := syscall.UTF16PtrFromString(string(title))
+		if err == nil {
+			procSetConsoleTitle.Call(uintptr(unsafe.Pointer(title8)))
+		}
+	}
+	return nil
+}
+
+// returns Atoi(s) unless s == "" in which case it returns def
+func atoiWithDefault(s string, def int) (int, error) {
+	if s == "" {
+		return def, nil
+	}
+	return strconv.Atoi(s)
+}
+
+// Write writes data on console
+func (w *Writer) Write(data []byte) (n int, err error) {
+	w.mutex.Lock()
+	defer w.mutex.Unlock()
+	var csbi consoleScreenBufferInfo
+	procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi)))
+
+	handle := w.handle
+
+	var er *bytes.Reader
+	if w.rest.Len() > 0 {
+		var rest bytes.Buffer
+		w.rest.WriteTo(&rest)
+		w.rest.Reset()
+		rest.Write(data)
+		er = bytes.NewReader(rest.Bytes())
+	} else {
+		er = bytes.NewReader(data)
+	}
+	var plaintext bytes.Buffer
+loop:
+	for {
+		c1, err := er.ReadByte()
+		if err != nil {
+			plaintext.WriteTo(w.out)
+			break loop
+		}
+		if c1 != 0x1b {
+			plaintext.WriteByte(c1)
+			continue
+		}
+		_, err = plaintext.WriteTo(w.out)
+		if err != nil {
+			break loop
+		}
+		c2, err := er.ReadByte()
+		if err != nil {
+			break loop
+		}
+
+		switch c2 {
+		case '>':
+			continue
+		case ']':
+			w.rest.WriteByte(c1)
+			w.rest.WriteByte(c2)
+			er.WriteTo(&w.rest)
+			if bytes.IndexByte(w.rest.Bytes(), 0x07) == -1 {
+				break loop
+			}
+			er = bytes.NewReader(w.rest.Bytes()[2:])
+			err := doTitleSequence(er)
+			if err != nil {
+				break loop
+			}
+			w.rest.Reset()
+			continue
+		// https://github.com/mattn/go-colorable/issues/27
+		case '7':
+			procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
+			w.oldpos = csbi.cursorPosition
+			continue
+		case '8':
+			procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&w.oldpos)))
+			continue
+		case 0x5b:
+			// execute part after switch
+		default:
+			continue
+		}
+
+		w.rest.WriteByte(c1)
+		w.rest.WriteByte(c2)
+		er.WriteTo(&w.rest)
+
+		var buf bytes.Buffer
+		var m byte
+		for i, c := range w.rest.Bytes()[2:] {
+			if ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || c == '@' {
+				m = c
+				er = bytes.NewReader(w.rest.Bytes()[2+i+1:])
+				w.rest.Reset()
+				break
+			}
+			buf.Write([]byte(string(c)))
+		}
+		if m == 0 {
+			break loop
+		}
+
+		switch m {
+		case 'A':
+			n, err = atoiWithDefault(buf.String(), 1)
+			if err != nil {
+				continue
+			}
+			procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
+			csbi.cursorPosition.y -= short(n)
+			procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
+		case 'B':
+			n, err = atoiWithDefault(buf.String(), 1)
+			if err != nil {
+				continue
+			}
+			procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
+			csbi.cursorPosition.y += short(n)
+			procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
+		case 'C':
+			n, err = atoiWithDefault(buf.String(), 1)
+			if err != nil {
+				continue
+			}
+			procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
+			csbi.cursorPosition.x += short(n)
+			procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
+		case 'D':
+			n, err = atoiWithDefault(buf.String(), 1)
+			if err != nil {
+				continue
+			}
+			procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
+			csbi.cursorPosition.x -= short(n)
+			if csbi.cursorPosition.x < 0 {
+				csbi.cursorPosition.x = 0
+			}
+			procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
+		case 'E':
+			n, err = strconv.Atoi(buf.String())
+			if err != nil {
+				continue
+			}
+			procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
+			csbi.cursorPosition.x = 0
+			csbi.cursorPosition.y += short(n)
+			procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
+		case 'F':
+			n, err = strconv.Atoi(buf.String())
+			if err != nil {
+				continue
+			}
+			procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
+			csbi.cursorPosition.x = 0
+			csbi.cursorPosition.y -= short(n)
+			procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
+		case 'G':
+			n, err = strconv.Atoi(buf.String())
+			if err != nil {
+				continue
+			}
+			if n < 1 {
+				n = 1
+			}
+			procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
+			csbi.cursorPosition.x = short(n - 1)
+			procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
+		case 'H', 'f':
+			procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
+			if buf.Len() > 0 {
+				token := strings.Split(buf.String(), ";")
+				switch len(token) {
+				case 1:
+					n1, err := strconv.Atoi(token[0])
+					if err != nil {
+						continue
+					}
+					csbi.cursorPosition.y = short(n1 - 1)
+				case 2:
+					n1, err := strconv.Atoi(token[0])
+					if err != nil {
+						continue
+					}
+					n2, err := strconv.Atoi(token[1])
+					if err != nil {
+						continue
+					}
+					csbi.cursorPosition.x = short(n2 - 1)
+					csbi.cursorPosition.y = short(n1 - 1)
+				}
+			} else {
+				csbi.cursorPosition.y = 0
+			}
+			procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
+		case 'J':
+			n := 0
+			if buf.Len() > 0 {
+				n, err = strconv.Atoi(buf.String())
+				if err != nil {
+					continue
+				}
+			}
+			var count, written dword
+			var cursor coord
+			procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
+			switch n {
+			case 0:
+				cursor = coord{x: csbi.cursorPosition.x, y: csbi.cursorPosition.y}
+				count = dword(csbi.size.x) - dword(csbi.cursorPosition.x) + dword(csbi.size.y-csbi.cursorPosition.y)*dword(csbi.size.x)
+			case 1:
+				cursor = coord{x: csbi.window.left, y: csbi.window.top}
+				count = dword(csbi.size.x) - dword(csbi.cursorPosition.x) + dword(csbi.window.top-csbi.cursorPosition.y)*dword(csbi.size.x)
+			case 2:
+				cursor = coord{x: csbi.window.left, y: csbi.window.top}
+				count = dword(csbi.size.x) - dword(csbi.cursorPosition.x) + dword(csbi.size.y-csbi.cursorPosition.y)*dword(csbi.size.x)
+			}
+			procFillConsoleOutputCharacter.Call(uintptr(handle), uintptr(' '), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written)))
+			procFillConsoleOutputAttribute.Call(uintptr(handle), uintptr(csbi.attributes), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written)))
+		case 'K':
+			n := 0
+			if buf.Len() > 0 {
+				n, err = strconv.Atoi(buf.String())
+				if err != nil {
+					continue
+				}
+			}
+			procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
+			var cursor coord
+			var count, written dword
+			switch n {
+			case 0:
+				cursor = coord{x: csbi.cursorPosition.x, y: csbi.cursorPosition.y}
+				count = dword(csbi.size.x - csbi.cursorPosition.x)
+			case 1:
+				cursor = coord{x: csbi.window.left, y: csbi.cursorPosition.y}
+				count = dword(csbi.size.x - csbi.cursorPosition.x)
+			case 2:
+				cursor = coord{x: csbi.window.left, y: csbi.cursorPosition.y}
+				count = dword(csbi.size.x)
+			}
+			procFillConsoleOutputCharacter.Call(uintptr(handle), uintptr(' '), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written)))
+			procFillConsoleOutputAttribute.Call(uintptr(handle), uintptr(csbi.attributes), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written)))
+		case 'X':
+			n := 0
+			if buf.Len() > 0 {
+				n, err = strconv.Atoi(buf.String())
+				if err != nil {
+					continue
+				}
+			}
+			procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
+			var cursor coord
+			var written dword
+			cursor = coord{x: csbi.cursorPosition.x, y: csbi.cursorPosition.y}
+			procFillConsoleOutputCharacter.Call(uintptr(handle), uintptr(' '), uintptr(n), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written)))
+			procFillConsoleOutputAttribute.Call(uintptr(handle), uintptr(csbi.attributes), uintptr(n), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written)))
+		case 'm':
+			procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
+			attr := csbi.attributes
+			cs := buf.String()
+			if cs == "" {
+				procSetConsoleTextAttribute.Call(uintptr(handle), uintptr(w.oldattr))
+				continue
+			}
+			token := strings.Split(cs, ";")
+			for i := 0; i < len(token); i++ {
+				ns := token[i]
+				if n, err = strconv.Atoi(ns); err == nil {
+					switch {
+					case n == 0 || n == 100:
+						attr = w.oldattr
+					case n == 4:
+						attr |= commonLvbUnderscore
+					case (1 <= n && n <= 3) || n == 5:
+						attr |= foregroundIntensity
+					case n == 7 || n == 27:
+						attr =
+							(attr &^ (foregroundMask | backgroundMask)) |
+								((attr & foregroundMask) << 4) |
+								((attr & backgroundMask) >> 4)
+					case n == 22:
+						attr &^= foregroundIntensity
+					case n == 24:
+						attr &^= commonLvbUnderscore
+					case 30 <= n && n <= 37:
+						attr &= backgroundMask
+						if (n-30)&1 != 0 {
+							attr |= foregroundRed
+						}
+						if (n-30)&2 != 0 {
+							attr |= foregroundGreen
+						}
+						if (n-30)&4 != 0 {
+							attr |= foregroundBlue
+						}
+					case n == 38: // set foreground color.
+						if i < len(token)-2 && (token[i+1] == "5" || token[i+1] == "05") {
+							if n256, err := strconv.Atoi(token[i+2]); err == nil {
+								if n256foreAttr == nil {
+									n256setup()
+								}
+								attr &= backgroundMask
+								attr |= n256foreAttr[n256%len(n256foreAttr)]
+								i += 2
+							}
+						} else if len(token) == 5 && token[i+1] == "2" {
+							var r, g, b int
+							r, _ = strconv.Atoi(token[i+2])
+							g, _ = strconv.Atoi(token[i+3])
+							b, _ = strconv.Atoi(token[i+4])
+							i += 4
+							if r > 127 {
+								attr |= foregroundRed
+							}
+							if g > 127 {
+								attr |= foregroundGreen
+							}
+							if b > 127 {
+								attr |= foregroundBlue
+							}
+						} else {
+							attr = attr & (w.oldattr & backgroundMask)
+						}
+					case n == 39: // reset foreground color.
+						attr &= backgroundMask
+						attr |= w.oldattr & foregroundMask
+					case 40 <= n && n <= 47:
+						attr &= foregroundMask
+						if (n-40)&1 != 0 {
+							attr |= backgroundRed
+						}
+						if (n-40)&2 != 0 {
+							attr |= backgroundGreen
+						}
+						if (n-40)&4 != 0 {
+							attr |= backgroundBlue
+						}
+					case n == 48: // set background color.
+						if i < len(token)-2 && token[i+1] == "5" {
+							if n256, err := strconv.Atoi(token[i+2]); err == nil {
+								if n256backAttr == nil {
+									n256setup()
+								}
+								attr &= foregroundMask
+								attr |= n256backAttr[n256%len(n256backAttr)]
+								i += 2
+							}
+						} else if len(token) == 5 && token[i+1] == "2" {
+							var r, g, b int
+							r, _ = strconv.Atoi(token[i+2])
+							g, _ = strconv.Atoi(token[i+3])
+							b, _ = strconv.Atoi(token[i+4])
+							i += 4
+							if r > 127 {
+								attr |= backgroundRed
+							}
+							if g > 127 {
+								attr |= backgroundGreen
+							}
+							if b > 127 {
+								attr |= backgroundBlue
+							}
+						} else {
+							attr = attr & (w.oldattr & foregroundMask)
+						}
+					case n == 49: // reset foreground color.
+						attr &= foregroundMask
+						attr |= w.oldattr & backgroundMask
+					case 90 <= n && n <= 97:
+						attr = (attr & backgroundMask)
+						attr |= foregroundIntensity
+						if (n-90)&1 != 0 {
+							attr |= foregroundRed
+						}
+						if (n-90)&2 != 0 {
+							attr |= foregroundGreen
+						}
+						if (n-90)&4 != 0 {
+							attr |= foregroundBlue
+						}
+					case 100 <= n && n <= 107:
+						attr = (attr & foregroundMask)
+						attr |= backgroundIntensity
+						if (n-100)&1 != 0 {
+							attr |= backgroundRed
+						}
+						if (n-100)&2 != 0 {
+							attr |= backgroundGreen
+						}
+						if (n-100)&4 != 0 {
+							attr |= backgroundBlue
+						}
+					}
+					procSetConsoleTextAttribute.Call(uintptr(handle), uintptr(attr))
+				}
+			}
+		case 'h':
+			var ci consoleCursorInfo
+			cs := buf.String()
+			if cs == "5>" {
+				procGetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&ci)))
+				ci.visible = 0
+				procSetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&ci)))
+			} else if cs == "?25" {
+				procGetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&ci)))
+				ci.visible = 1
+				procSetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&ci)))
+			} else if cs == "?1049" {
+				if w.althandle == 0 {
+					h, _, _ := procCreateConsoleScreenBuffer.Call(uintptr(genericRead|genericWrite), 0, 0, uintptr(consoleTextmodeBuffer), 0, 0)
+					w.althandle = syscall.Handle(h)
+					if w.althandle != 0 {
+						handle = w.althandle
+					}
+				}
+			}
+		case 'l':
+			var ci consoleCursorInfo
+			cs := buf.String()
+			if cs == "5>" {
+				procGetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&ci)))
+				ci.visible = 1
+				procSetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&ci)))
+			} else if cs == "?25" {
+				procGetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&ci)))
+				ci.visible = 0
+				procSetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&ci)))
+			} else if cs == "?1049" {
+				if w.althandle != 0 {
+					syscall.CloseHandle(w.althandle)
+					w.althandle = 0
+					handle = w.handle
+				}
+			}
+		case 's':
+			procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
+			w.oldpos = csbi.cursorPosition
+		case 'u':
+			procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&w.oldpos)))
+		}
+	}
+
+	return len(data), nil
+}
+
+type consoleColor struct {
+	rgb       int
+	red       bool
+	green     bool
+	blue      bool
+	intensity bool
+}
+
+func (c consoleColor) foregroundAttr() (attr word) {
+	if c.red {
+		attr |= foregroundRed
+	}
+	if c.green {
+		attr |= foregroundGreen
+	}
+	if c.blue {
+		attr |= foregroundBlue
+	}
+	if c.intensity {
+		attr |= foregroundIntensity
+	}
+	return
+}
+
+func (c consoleColor) backgroundAttr() (attr word) {
+	if c.red {
+		attr |= backgroundRed
+	}
+	if c.green {
+		attr |= backgroundGreen
+	}
+	if c.blue {
+		attr |= backgroundBlue
+	}
+	if c.intensity {
+		attr |= backgroundIntensity
+	}
+	return
+}
+
+var color16 = []consoleColor{
+	{0x000000, false, false, false, false},
+	{0x000080, false, false, true, false},
+	{0x008000, false, true, false, false},
+	{0x008080, false, true, true, false},
+	{0x800000, true, false, false, false},
+	{0x800080, true, false, true, false},
+	{0x808000, true, true, false, false},
+	{0xc0c0c0, true, true, true, false},
+	{0x808080, false, false, false, true},
+	{0x0000ff, false, false, true, true},
+	{0x00ff00, false, true, false, true},
+	{0x00ffff, false, true, true, true},
+	{0xff0000, true, false, false, true},
+	{0xff00ff, true, false, true, true},
+	{0xffff00, true, true, false, true},
+	{0xffffff, true, true, true, true},
+}
+
+type hsv struct {
+	h, s, v float32
+}
+
+func (a hsv) dist(b hsv) float32 {
+	dh := a.h - b.h
+	switch {
+	case dh > 0.5:
+		dh = 1 - dh
+	case dh < -0.5:
+		dh = -1 - dh
+	}
+	ds := a.s - b.s
+	dv := a.v - b.v
+	return float32(math.Sqrt(float64(dh*dh + ds*ds + dv*dv)))
+}
+
+func toHSV(rgb int) hsv {
+	r, g, b := float32((rgb&0xFF0000)>>16)/256.0,
+		float32((rgb&0x00FF00)>>8)/256.0,
+		float32(rgb&0x0000FF)/256.0
+	min, max := minmax3f(r, g, b)
+	h := max - min
+	if h > 0 {
+		if max == r {
+			h = (g - b) / h
+			if h < 0 {
+				h += 6
+			}
+		} else if max == g {
+			h = 2 + (b-r)/h
+		} else {
+			h = 4 + (r-g)/h
+		}
+	}
+	h /= 6.0
+	s := max - min
+	if max != 0 {
+		s /= max
+	}
+	v := max
+	return hsv{h: h, s: s, v: v}
+}
+
+type hsvTable []hsv
+
+func toHSVTable(rgbTable []consoleColor) hsvTable {
+	t := make(hsvTable, len(rgbTable))
+	for i, c := range rgbTable {
+		t[i] = toHSV(c.rgb)
+	}
+	return t
+}
+
+func (t hsvTable) find(rgb int) consoleColor {
+	hsv := toHSV(rgb)
+	n := 7
+	l := float32(5.0)
+	for i, p := range t {
+		d := hsv.dist(p)
+		if d < l {
+			l, n = d, i
+		}
+	}
+	return color16[n]
+}
+
+func minmax3f(a, b, c float32) (min, max float32) {
+	if a < b {
+		if b < c {
+			return a, c
+		} else if a < c {
+			return a, b
+		} else {
+			return c, b
+		}
+	} else {
+		if a < c {
+			return b, c
+		} else if b < c {
+			return b, a
+		} else {
+			return c, a
+		}
+	}
+}
+
+var n256foreAttr []word
+var n256backAttr []word
+
+func n256setup() {
+	n256foreAttr = make([]word, 256)
+	n256backAttr = make([]word, 256)
+	t := toHSVTable(color16)
+	for i, rgb := range color256 {
+		c := t.find(rgb)
+		n256foreAttr[i] = c.foregroundAttr()
+		n256backAttr[i] = c.backgroundAttr()
+	}
+}
+
+// EnableColorsStdout enable colors if possible.
+func EnableColorsStdout(enabled *bool) func() {
+	var mode uint32
+	h := os.Stdout.Fd()
+	if r, _, _ := procGetConsoleMode.Call(h, uintptr(unsafe.Pointer(&mode))); r != 0 {
+		if r, _, _ = procSetConsoleMode.Call(h, uintptr(mode|cENABLE_VIRTUAL_TERMINAL_PROCESSING)); r != 0 {
+			if enabled != nil {
+				*enabled = true
+			}
+			return func() {
+				procSetConsoleMode.Call(h, uintptr(mode))
+			}
+		}
+	}
+	if enabled != nil {
+		*enabled = true
+	}
+	return func() {}
+}
diff --git a/vendor/github.com/mattn/go-colorable/go.test.sh b/vendor/github.com/mattn/go-colorable/go.test.sh
new file mode 100644
index 0000000000..012162b077
--- /dev/null
+++ b/vendor/github.com/mattn/go-colorable/go.test.sh
@@ -0,0 +1,12 @@
+#!/usr/bin/env bash
+
+set -e
+echo "" > coverage.txt
+
+for d in $(go list ./... | grep -v vendor); do
+    go test -race -coverprofile=profile.out -covermode=atomic "$d"
+    if [ -f profile.out ]; then
+        cat profile.out >> coverage.txt
+        rm profile.out
+    fi
+done
diff --git a/vendor/github.com/mattn/go-colorable/noncolorable.go b/vendor/github.com/mattn/go-colorable/noncolorable.go
new file mode 100644
index 0000000000..05d6f74bf6
--- /dev/null
+++ b/vendor/github.com/mattn/go-colorable/noncolorable.go
@@ -0,0 +1,57 @@
+package colorable
+
+import (
+	"bytes"
+	"io"
+)
+
+// NonColorable holds writer but removes escape sequence.
+type NonColorable struct {
+	out io.Writer
+}
+
+// NewNonColorable returns new instance of Writer which removes escape sequence from Writer.
+func NewNonColorable(w io.Writer) io.Writer {
+	return &NonColorable{out: w}
+}
+
+// Write writes data on console
+func (w *NonColorable) Write(data []byte) (n int, err error) {
+	er := bytes.NewReader(data)
+	var plaintext bytes.Buffer
+loop:
+	for {
+		c1, err := er.ReadByte()
+		if err != nil {
+			plaintext.WriteTo(w.out)
+			break loop
+		}
+		if c1 != 0x1b {
+			plaintext.WriteByte(c1)
+			continue
+		}
+		_, err = plaintext.WriteTo(w.out)
+		if err != nil {
+			break loop
+		}
+		c2, err := er.ReadByte()
+		if err != nil {
+			break loop
+		}
+		if c2 != 0x5b {
+			continue
+		}
+
+		for {
+			c, err := er.ReadByte()
+			if err != nil {
+				break loop
+			}
+			if ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || c == '@' {
+				break
+			}
+		}
+	}
+
+	return len(data), nil
+}
diff --git a/vendor/gopkg.in/natefinch/lumberjack.v2/.gitignore b/vendor/gopkg.in/natefinch/lumberjack.v2/.gitignore
new file mode 100644
index 0000000000..836562412f
--- /dev/null
+++ b/vendor/gopkg.in/natefinch/lumberjack.v2/.gitignore
@@ -0,0 +1,23 @@
+# Compiled Object files, Static and Dynamic libs (Shared Objects)
+*.o
+*.a
+*.so
+
+# Folders
+_obj
+_test
+
+# Architecture specific extensions/prefixes
+*.[568vq]
+[568vq].out
+
+*.cgo1.go
+*.cgo2.c
+_cgo_defun.c
+_cgo_gotypes.go
+_cgo_export.*
+
+_testmain.go
+
+*.exe
+*.test
diff --git a/vendor/gopkg.in/natefinch/lumberjack.v2/.travis.yml b/vendor/gopkg.in/natefinch/lumberjack.v2/.travis.yml
new file mode 100644
index 0000000000..21166f5c7d
--- /dev/null
+++ b/vendor/gopkg.in/natefinch/lumberjack.v2/.travis.yml
@@ -0,0 +1,11 @@
+language: go
+
+go:
+  - tip
+  - 1.15.x
+  - 1.14.x
+  - 1.13.x
+  - 1.12.x
+  
+env:
+  - GO111MODULE=on
diff --git a/vendor/gopkg.in/natefinch/lumberjack.v2/LICENSE b/vendor/gopkg.in/natefinch/lumberjack.v2/LICENSE
new file mode 100644
index 0000000000..c3d4cc307d
--- /dev/null
+++ b/vendor/gopkg.in/natefinch/lumberjack.v2/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2014 Nate Finch 
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
\ No newline at end of file
diff --git a/vendor/gopkg.in/natefinch/lumberjack.v2/README.md b/vendor/gopkg.in/natefinch/lumberjack.v2/README.md
new file mode 100644
index 0000000000..060eae52a2
--- /dev/null
+++ b/vendor/gopkg.in/natefinch/lumberjack.v2/README.md
@@ -0,0 +1,179 @@
+# lumberjack  [![GoDoc](https://godoc.org/gopkg.in/natefinch/lumberjack.v2?status.png)](https://godoc.org/gopkg.in/natefinch/lumberjack.v2) [![Build Status](https://travis-ci.org/natefinch/lumberjack.svg?branch=v2.0)](https://travis-ci.org/natefinch/lumberjack) [![Build status](https://ci.appveyor.com/api/projects/status/00gchpxtg4gkrt5d)](https://ci.appveyor.com/project/natefinch/lumberjack) [![Coverage Status](https://coveralls.io/repos/natefinch/lumberjack/badge.svg?branch=v2.0)](https://coveralls.io/r/natefinch/lumberjack?branch=v2.0)
+
+### Lumberjack is a Go package for writing logs to rolling files.
+
+Package lumberjack provides a rolling logger.
+
+Note that this is v2.0 of lumberjack, and should be imported using gopkg.in
+thusly:
+
+    import "gopkg.in/natefinch/lumberjack.v2"
+
+The package name remains simply lumberjack, and the code resides at
+https://github.com/natefinch/lumberjack under the v2.0 branch.
+
+Lumberjack is intended to be one part of a logging infrastructure.
+It is not an all-in-one solution, but instead is a pluggable
+component at the bottom of the logging stack that simply controls the files
+to which logs are written.
+
+Lumberjack plays well with any logging package that can write to an
+io.Writer, including the standard library's log package.
+
+Lumberjack assumes that only one process is writing to the output files.
+Using the same lumberjack configuration from multiple processes on the same
+machine will result in improper behavior.
+
+
+**Example**
+
+To use lumberjack with the standard library's log package, just pass it into the SetOutput function when your application starts.
+
+Code:
+
+```go
+log.SetOutput(&lumberjack.Logger{
+    Filename:   "/var/log/myapp/foo.log",
+    MaxSize:    500, // megabytes
+    MaxBackups: 3,
+    MaxAge:     28, //days
+    Compress:   true, // disabled by default
+})
+```
+
+
+
+## type Logger
+``` go
+type Logger struct {
+    // Filename is the file to write logs to.  Backup log files will be retained
+    // in the same directory.  It uses <processname>-lumberjack.log in
+    // os.TempDir() if empty.
+    Filename string `json:"filename" yaml:"filename"`
+
+    // MaxSize is the maximum size in megabytes of the log file before it gets
+    // rotated. It defaults to 100 megabytes.
+    MaxSize int `json:"maxsize" yaml:"maxsize"`
+
+    // MaxAge is the maximum number of days to retain old log files based on the
+    // timestamp encoded in their filename.  Note that a day is defined as 24
+    // hours and may not exactly correspond to calendar days due to daylight
+    // savings, leap seconds, etc. The default is not to remove old log files
+    // based on age.
+    MaxAge int `json:"maxage" yaml:"maxage"`
+
+    // MaxBackups is the maximum number of old log files to retain.  The default
+    // is to retain all old log files (though MaxAge may still cause them to get
+    // deleted.)
+    MaxBackups int `json:"maxbackups" yaml:"maxbackups"`
+
+    // LocalTime determines if the time used for formatting the timestamps in
+    // backup files is the computer's local time.  The default is to use UTC
+    // time.
+    LocalTime bool `json:"localtime" yaml:"localtime"`
+
+    // Compress determines if the rotated log files should be compressed
+    // using gzip. The default is not to perform compression.
+    Compress bool `json:"compress" yaml:"compress"`
+    // contains filtered or unexported fields
+}
+```
+Logger is an io.WriteCloser that writes to the specified filename.
+
+Logger opens or creates the logfile on first Write.  If the file exists and
+is less than MaxSize megabytes, lumberjack will open and append to that file.
+If the file exists and its size is >= MaxSize megabytes, the file is renamed
+by putting the current time in a timestamp in the name immediately before the
+file's extension (or the end of the filename if there's no extension). A new
+log file is then created using original filename.
+
+Whenever a write would cause the current log file exceed MaxSize megabytes,
+the current file is closed, renamed, and a new log file created with the
+original name. Thus, the filename you give Logger is always the "current" log
+file.
+
+Backups use the log file name given to Logger, in the form `name-timestamp.ext`
+where name is the filename without the extension, timestamp is the time at which
+the log was rotated formatted with the time.Time format of
+`2006-01-02T15-04-05.000` and the extension is the original extension.  For
+example, if your Logger.Filename is `/var/log/foo/server.log`, a backup created
+at 6:30pm on Nov 11 2016 would use the filename
+`/var/log/foo/server-2016-11-04T18-30-00.000.log`
+
+### Cleaning Up Old Log Files
+Whenever a new logfile gets created, old log files may be deleted.  The most
+recent files according to the encoded timestamp will be retained, up to a
+number equal to MaxBackups (or all of them if MaxBackups is 0).  Any files
+with an encoded timestamp older than MaxAge days are deleted, regardless of
+MaxBackups.  Note that the time encoded in the timestamp is the rotation
+time, which may differ from the last time that file was written to.
+
+If MaxBackups and MaxAge are both 0, no old log files will be deleted.
+
+
+
+
+
+
+
+
+
+
+
+### func (\*Logger) Close
+``` go
+func (l *Logger) Close() error
+```
+Close implements io.Closer, and closes the current logfile.
+
+
+
+### func (\*Logger) Rotate
+``` go
+func (l *Logger) Rotate() error
+```
+Rotate causes Logger to close the existing log file and immediately create a
+new one.  This is a helper function for applications that want to initiate
+rotations outside of the normal rotation rules, such as in response to
+SIGHUP.  After rotating, this initiates a cleanup of old log files according
+to the normal rules.
+
+**Example**
+
+Example of how to rotate in response to SIGHUP.
+
+Code:
+
+```go
+l := &lumberjack.Logger{}
+log.SetOutput(l)
+c := make(chan os.Signal, 1)
+signal.Notify(c, syscall.SIGHUP)
+
+go func() {
+    for {
+        <-c
+        l.Rotate()
+    }
+}()
+```
+
+### func (\*Logger) Write
+``` go
+func (l *Logger) Write(p []byte) (n int, err error)
+```
+Write implements io.Writer.  If a write would cause the log file to be larger
+than MaxSize, the file is closed, renamed to include a timestamp of the
+current time, and a new log file is created using the original log file name.
+If the length of the write is greater than MaxSize, an error is returned.
+
+
+
+
+
+
+
+
+
+- - -
+Generated by [godoc2md](http://godoc.org/github.com/davecheney/godoc2md)
diff --git a/vendor/gopkg.in/natefinch/lumberjack.v2/chown.go b/vendor/gopkg.in/natefinch/lumberjack.v2/chown.go
new file mode 100644
index 0000000000..11d0669723
--- /dev/null
+++ b/vendor/gopkg.in/natefinch/lumberjack.v2/chown.go
@@ -0,0 +1,11 @@
+// +build !linux
+
+package lumberjack
+
+import (
+	"os"
+)
+
+func chown(_ string, _ os.FileInfo) error {
+	return nil
+}
diff --git a/vendor/gopkg.in/natefinch/lumberjack.v2/chown_linux.go b/vendor/gopkg.in/natefinch/lumberjack.v2/chown_linux.go
new file mode 100644
index 0000000000..465f569270
--- /dev/null
+++ b/vendor/gopkg.in/natefinch/lumberjack.v2/chown_linux.go
@@ -0,0 +1,19 @@
+package lumberjack
+
+import (
+	"os"
+	"syscall"
+)
+
+// osChown is a var so we can mock it out during tests.
+var osChown = os.Chown
+
+func chown(name string, info os.FileInfo) error {
+	f, err := os.OpenFile(name, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, info.Mode())
+	if err != nil {
+		return err
+	}
+	f.Close()
+	stat := info.Sys().(*syscall.Stat_t)
+	return osChown(name, int(stat.Uid), int(stat.Gid))
+}
diff --git a/vendor/gopkg.in/natefinch/lumberjack.v2/lumberjack.go b/vendor/gopkg.in/natefinch/lumberjack.v2/lumberjack.go
new file mode 100644
index 0000000000..3447cdc056
--- /dev/null
+++ b/vendor/gopkg.in/natefinch/lumberjack.v2/lumberjack.go
@@ -0,0 +1,541 @@
+// Package lumberjack provides a rolling logger.
+//
+// Note that this is v2.0 of lumberjack, and should be imported using gopkg.in
+// thusly:
+//
+//   import "gopkg.in/natefinch/lumberjack.v2"
+//
+// The package name remains simply lumberjack, and the code resides at
+// https://github.com/natefinch/lumberjack under the v2.0 branch.
+//
+// Lumberjack is intended to be one part of a logging infrastructure.
+// It is not an all-in-one solution, but instead is a pluggable
+// component at the bottom of the logging stack that simply controls the files
+// to which logs are written.
+//
+// Lumberjack plays well with any logging package that can write to an
+// io.Writer, including the standard library's log package.
+//
+// Lumberjack assumes that only one process is writing to the output files.
+// Using the same lumberjack configuration from multiple processes on the same
+// machine will result in improper behavior.
+package lumberjack
+
+import (
+	"compress/gzip"
+	"errors"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"os"
+	"path/filepath"
+	"sort"
+	"strings"
+	"sync"
+	"time"
+)
+
+const (
+	backupTimeFormat = "2006-01-02T15-04-05.000"
+	compressSuffix   = ".gz"
+	defaultMaxSize   = 100
+)
+
+// ensure we always implement io.WriteCloser
+var _ io.WriteCloser = (*Logger)(nil)
+
+// Logger is an io.WriteCloser that writes to the specified filename.
+//
+// Logger opens or creates the logfile on first Write.  If the file exists and
+// is less than MaxSize megabytes, lumberjack will open and append to that file.
+// If the file exists and its size is >= MaxSize megabytes, the file is renamed
+// by putting the current time in a timestamp in the name immediately before the
+// file's extension (or the end of the filename if there's no extension). A new
+// log file is then created using original filename.
+//
+// Whenever a write would cause the current log file exceed MaxSize megabytes,
+// the current file is closed, renamed, and a new log file created with the
+// original name. Thus, the filename you give Logger is always the "current" log
+// file.
+//
+// Backups use the log file name given to Logger, in the form
+// `name-timestamp.ext` where name is the filename without the extension,
+// timestamp is the time at which the log was rotated formatted with the
+// time.Time format of `2006-01-02T15-04-05.000` and the extension is the
+// original extension.  For example, if your Logger.Filename is
+// `/var/log/foo/server.log`, a backup created at 6:30pm on Nov 11 2016 would
+// use the filename `/var/log/foo/server-2016-11-04T18-30-00.000.log`
+//
+// Cleaning Up Old Log Files
+//
+// Whenever a new logfile gets created, old log files may be deleted.  The most
+// recent files according to the encoded timestamp will be retained, up to a
+// number equal to MaxBackups (or all of them if MaxBackups is 0).  Any files
+// with an encoded timestamp older than MaxAge days are deleted, regardless of
+// MaxBackups.  Note that the time encoded in the timestamp is the rotation
+// time, which may differ from the last time that file was written to.
+//
+// If MaxBackups and MaxAge are both 0, no old log files will be deleted.
+type Logger struct {
+	// Filename is the file to write logs to.  Backup log files will be retained
+	// in the same directory.  It uses <processname>-lumberjack.log in
+	// os.TempDir() if empty.
+	Filename string `json:"filename" yaml:"filename"`
+
+	// MaxSize is the maximum size in megabytes of the log file before it gets
+	// rotated. It defaults to 100 megabytes.
+	MaxSize int `json:"maxsize" yaml:"maxsize"`
+
+	// MaxAge is the maximum number of days to retain old log files based on the
+	// timestamp encoded in their filename.  Note that a day is defined as 24
+	// hours and may not exactly correspond to calendar days due to daylight
+	// savings, leap seconds, etc. The default is not to remove old log files
+	// based on age.
+	MaxAge int `json:"maxage" yaml:"maxage"`
+
+	// MaxBackups is the maximum number of old log files to retain.  The default
+	// is to retain all old log files (though MaxAge may still cause them to get
+	// deleted.)
+	MaxBackups int `json:"maxbackups" yaml:"maxbackups"`
+
+	// LocalTime determines if the time used for formatting the timestamps in
+	// backup files is the computer's local time.  The default is to use UTC
+	// time.
+	LocalTime bool `json:"localtime" yaml:"localtime"`
+
+	// Compress determines if the rotated log files should be compressed
+	// using gzip. The default is not to perform compression.
+	Compress bool `json:"compress" yaml:"compress"`
+
+	size int64
+	file *os.File
+	mu   sync.Mutex
+
+	millCh    chan bool
+	startMill sync.Once
+}
+
+var (
+	// currentTime exists so it can be mocked out by tests.
+	currentTime = time.Now
+
+	// os_Stat exists so it can be mocked out by tests.
+	osStat = os.Stat
+
+	// megabyte is the conversion factor between MaxSize and bytes.  It is a
+	// variable so tests can mock it out and not need to write megabytes of data
+	// to disk.
+	megabyte = 1024 * 1024
+)
+
+// Write implements io.Writer.  If a write would cause the log file to be larger
+// than MaxSize, the file is closed, renamed to include a timestamp of the
+// current time, and a new log file is created using the original log file name.
+// If the length of the write is greater than MaxSize, an error is returned.
+func (l *Logger) Write(p []byte) (n int, err error) {
+	l.mu.Lock()
+	defer l.mu.Unlock()
+
+	writeLen := int64(len(p))
+	if writeLen > l.max() {
+		return 0, fmt.Errorf(
+			"write length %d exceeds maximum file size %d", writeLen, l.max(),
+		)
+	}
+
+	if l.file == nil {
+		if err = l.openExistingOrNew(len(p)); err != nil {
+			return 0, err
+		}
+	}
+
+	if l.size+writeLen > l.max() {
+		if err := l.rotate(); err != nil {
+			return 0, err
+		}
+	}
+
+	n, err = l.file.Write(p)
+	l.size += int64(n)
+
+	return n, err
+}
+
+// Close implements io.Closer, and closes the current logfile.
+func (l *Logger) Close() error {
+	l.mu.Lock()
+	defer l.mu.Unlock()
+	return l.close()
+}
+
+// close closes the file if it is open.
+func (l *Logger) close() error {
+	if l.file == nil {
+		return nil
+	}
+	err := l.file.Close()
+	l.file = nil
+	return err
+}
+
+// Rotate causes Logger to close the existing log file and immediately create a
+// new one.  This is a helper function for applications that want to initiate
+// rotations outside of the normal rotation rules, such as in response to
+// SIGHUP.  After rotating, this initiates compression and removal of old log
+// files according to the configuration.
+func (l *Logger) Rotate() error {
+	l.mu.Lock()
+	defer l.mu.Unlock()
+	return l.rotate()
+}
+
+// rotate closes the current file, moves it aside with a timestamp in the name,
+// (if it exists), opens a new file with the original filename, and then runs
+// post-rotation processing and removal.
+func (l *Logger) rotate() error {
+	if err := l.close(); err != nil {
+		return err
+	}
+	if err := l.openNew(); err != nil {
+		return err
+	}
+	l.mill()
+	return nil
+}
+
+// openNew opens a new log file for writing, moving any old log file out of the
+// way.  This methods assumes the file has already been closed.
+func (l *Logger) openNew() error {
+	err := os.MkdirAll(l.dir(), 0755)
+	if err != nil {
+		return fmt.Errorf("can't make directories for new logfile: %s", err)
+	}
+
+	name := l.filename()
+	mode := os.FileMode(0600)
+	info, err := osStat(name)
+	if err == nil {
+		// Copy the mode off the old logfile.
+		mode = info.Mode()
+		// move the existing file
+		newname := backupName(name, l.LocalTime)
+		if err := os.Rename(name, newname); err != nil {
+			return fmt.Errorf("can't rename log file: %s", err)
+		}
+
+		// this is a no-op anywhere but linux
+		if err := chown(name, info); err != nil {
+			return err
+		}
+	}
+
+	// we use truncate here because this should only get called when we've moved
+	// the file ourselves. if someone else creates the file in the meantime,
+	// just wipe out the contents.
+	f, err := os.OpenFile(name, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, mode)
+	if err != nil {
+		return fmt.Errorf("can't open new logfile: %s", err)
+	}
+	l.file = f
+	l.size = 0
+	return nil
+}
+
+// backupName creates a new filename from the given name, inserting a timestamp
+// between the filename and the extension, using the local time if requested
+// (otherwise UTC).
+func backupName(name string, local bool) string {
+	dir := filepath.Dir(name)
+	filename := filepath.Base(name)
+	ext := filepath.Ext(filename)
+	prefix := filename[:len(filename)-len(ext)]
+	t := currentTime()
+	if !local {
+		t = t.UTC()
+	}
+
+	timestamp := t.Format(backupTimeFormat)
+	return filepath.Join(dir, fmt.Sprintf("%s-%s%s", prefix, timestamp, ext))
+}
+
+// openExistingOrNew opens the logfile if it exists and if the current write
+// would not put it over MaxSize.  If there is no such file or the write would
+// put it over the MaxSize, a new file is created.
+func (l *Logger) openExistingOrNew(writeLen int) error {
+	l.mill()
+
+	filename := l.filename()
+	info, err := osStat(filename)
+	if os.IsNotExist(err) {
+		return l.openNew()
+	}
+	if err != nil {
+		return fmt.Errorf("error getting log file info: %s", err)
+	}
+
+	if info.Size()+int64(writeLen) >= l.max() {
+		return l.rotate()
+	}
+
+	file, err := os.OpenFile(filename, os.O_APPEND|os.O_WRONLY, 0644)
+	if err != nil {
+		// if we fail to open the old log file for some reason, just ignore
+		// it and open a new log file.
+		return l.openNew()
+	}
+	l.file = file
+	l.size = info.Size()
+	return nil
+}
+
+// filename generates the name of the logfile from the current time.
+func (l *Logger) filename() string {
+	if l.Filename != "" {
+		return l.Filename
+	}
+	name := filepath.Base(os.Args[0]) + "-lumberjack.log"
+	return filepath.Join(os.TempDir(), name)
+}
+
+// millRunOnce performs compression and removal of stale log files.
+// Log files are compressed if enabled via configuration and old log
+// files are removed, keeping at most l.MaxBackups files, as long as
+// none of them are older than MaxAge.
+func (l *Logger) millRunOnce() error {
+	if l.MaxBackups == 0 && l.MaxAge == 0 && !l.Compress {
+		return nil
+	}
+
+	files, err := l.oldLogFiles()
+	if err != nil {
+		return err
+	}
+
+	var compress, remove []logInfo
+
+	if l.MaxBackups > 0 && l.MaxBackups < len(files) {
+		preserved := make(map[string]bool)
+		var remaining []logInfo
+		for _, f := range files {
+			// Only count the uncompressed log file or the
+			// compressed log file, not both.
+			fn := f.Name()
+			if strings.HasSuffix(fn, compressSuffix) {
+				fn = fn[:len(fn)-len(compressSuffix)]
+			}
+			preserved[fn] = true
+
+			if len(preserved) > l.MaxBackups {
+				remove = append(remove, f)
+			} else {
+				remaining = append(remaining, f)
+			}
+		}
+		files = remaining
+	}
+	if l.MaxAge > 0 {
+		diff := time.Duration(int64(24*time.Hour) * int64(l.MaxAge))
+		cutoff := currentTime().Add(-1 * diff)
+
+		var remaining []logInfo
+		for _, f := range files {
+			if f.timestamp.Before(cutoff) {
+				remove = append(remove, f)
+			} else {
+				remaining = append(remaining, f)
+			}
+		}
+		files = remaining
+	}
+
+	if l.Compress {
+		for _, f := range files {
+			if !strings.HasSuffix(f.Name(), compressSuffix) {
+				compress = append(compress, f)
+			}
+		}
+	}
+
+	for _, f := range remove {
+		errRemove := os.Remove(filepath.Join(l.dir(), f.Name()))
+		if err == nil && errRemove != nil {
+			err = errRemove
+		}
+	}
+	for _, f := range compress {
+		fn := filepath.Join(l.dir(), f.Name())
+		errCompress := compressLogFile(fn, fn+compressSuffix)
+		if err == nil && errCompress != nil {
+			err = errCompress
+		}
+	}
+
+	return err
+}
+
+// millRun runs in a goroutine to manage post-rotation compression and removal
+// of old log files.
+func (l *Logger) millRun() {
+	for range l.millCh {
+		// what am I going to do, log this?
+		_ = l.millRunOnce()
+	}
+}
+
+// mill performs post-rotation compression and removal of stale log files,
+// starting the mill goroutine if necessary.
+func (l *Logger) mill() {
+	l.startMill.Do(func() {
+		l.millCh = make(chan bool, 1)
+		go l.millRun()
+	})
+	select {
+	case l.millCh <- true:
+	default:
+	}
+}
+
+// oldLogFiles returns the list of backup log files stored in the same
+// directory as the current log file, sorted by ModTime
+func (l *Logger) oldLogFiles() ([]logInfo, error) {
+	files, err := ioutil.ReadDir(l.dir())
+	if err != nil {
+		return nil, fmt.Errorf("can't read log file directory: %s", err)
+	}
+	logFiles := []logInfo{}
+
+	prefix, ext := l.prefixAndExt()
+
+	for _, f := range files {
+		if f.IsDir() {
+			continue
+		}
+		if t, err := l.timeFromName(f.Name(), prefix, ext); err == nil {
+			logFiles = append(logFiles, logInfo{t, f})
+			continue
+		}
+		if t, err := l.timeFromName(f.Name(), prefix, ext+compressSuffix); err == nil {
+			logFiles = append(logFiles, logInfo{t, f})
+			continue
+		}
+		// error parsing means that the suffix at the end was not generated
+		// by lumberjack, and therefore it's not a backup file.
+	}
+
+	sort.Sort(byFormatTime(logFiles))
+
+	return logFiles, nil
+}
+
+// timeFromName extracts the formatted time from the filename by stripping off
+// the filename's prefix and extension. This prevents someone's filename from
+// confusing time.parse.
+func (l *Logger) timeFromName(filename, prefix, ext string) (time.Time, error) {
+	if !strings.HasPrefix(filename, prefix) {
+		return time.Time{}, errors.New("mismatched prefix")
+	}
+	if !strings.HasSuffix(filename, ext) {
+		return time.Time{}, errors.New("mismatched extension")
+	}
+	ts := filename[len(prefix) : len(filename)-len(ext)]
+	return time.Parse(backupTimeFormat, ts)
+}
+
+// max returns the maximum size in bytes of log files before rolling.
+func (l *Logger) max() int64 {
+	if l.MaxSize == 0 {
+		return int64(defaultMaxSize * megabyte)
+	}
+	return int64(l.MaxSize) * int64(megabyte)
+}
+
+// dir returns the directory for the current filename.
+func (l *Logger) dir() string {
+	return filepath.Dir(l.filename())
+}
+
+// prefixAndExt returns the filename part and extension part from the Logger's
+// filename.
+func (l *Logger) prefixAndExt() (prefix, ext string) {
+	filename := filepath.Base(l.filename())
+	ext = filepath.Ext(filename)
+	prefix = filename[:len(filename)-len(ext)] + "-"
+	return prefix, ext
+}
+
+// compressLogFile compresses the given log file, removing the
+// uncompressed log file if successful.
+func compressLogFile(src, dst string) (err error) {
+	f, err := os.Open(src)
+	if err != nil {
+		return fmt.Errorf("failed to open log file: %v", err)
+	}
+	defer f.Close()
+
+	fi, err := osStat(src)
+	if err != nil {
+		return fmt.Errorf("failed to stat log file: %v", err)
+	}
+
+	if err := chown(dst, fi); err != nil {
+		return fmt.Errorf("failed to chown compressed log file: %v", err)
+	}
+
+	// If this file already exists, we presume it was created by
+	// a previous attempt to compress the log file.
+	gzf, err := os.OpenFile(dst, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, fi.Mode())
+	if err != nil {
+		return fmt.Errorf("failed to open compressed log file: %v", err)
+	}
+	defer gzf.Close()
+
+	gz := gzip.NewWriter(gzf)
+
+	defer func() {
+		if err != nil {
+			os.Remove(dst)
+			err = fmt.Errorf("failed to compress log file: %v", err)
+		}
+	}()
+
+	if _, err := io.Copy(gz, f); err != nil {
+		return err
+	}
+	if err := gz.Close(); err != nil {
+		return err
+	}
+	if err := gzf.Close(); err != nil {
+		return err
+	}
+
+	if err := f.Close(); err != nil {
+		return err
+	}
+	if err := os.Remove(src); err != nil {
+		return err
+	}
+
+	return nil
+}
+
+// logInfo is a convenience struct to return the filename and its embedded
+// timestamp.
+type logInfo struct {
+	timestamp time.Time
+	os.FileInfo
+}
+
+// byFormatTime sorts by newest time formatted in the name.
+type byFormatTime []logInfo
+
+func (b byFormatTime) Less(i, j int) bool {
+	return b[i].timestamp.After(b[j].timestamp)
+}
+
+func (b byFormatTime) Swap(i, j int) {
+	b[i], b[j] = b[j], b[i]
+}
+
+func (b byFormatTime) Len() int {
+	return len(b)
+}
diff --git a/vendor/modules.txt b/vendor/modules.txt
index e53019ae68..0e8e37f9d2 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -423,6 +423,10 @@ github.com/coreos/stream-metadata-go/release
 github.com/coreos/stream-metadata-go/release/rhcos
 github.com/coreos/stream-metadata-go/stream
 github.com/coreos/stream-metadata-go/stream/rhcos
+# github.com/crc-org/crc/v2 v2.32.0
+## explicit; go 1.20
+github.com/crc-org/crc/v2/pkg/crc/logging
+github.com/crc-org/crc/v2/pkg/os
 # github.com/crc-org/vfkit v0.5.0
 ## explicit; go 1.18
 github.com/crc-org/vfkit/pkg/cmdline
@@ -436,7 +440,7 @@ github.com/cyberphone/json-canonicalization/go/src/webpki.org/jsoncanonicalizer
 # github.com/cyphar/filepath-securejoin v0.2.4
 ## explicit; go 1.13
 github.com/cyphar/filepath-securejoin
-# github.com/davecgh/go-spew v1.1.1
+# github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc
 ## explicit
 github.com/davecgh/go-spew/spew
 # github.com/digitalocean/go-libvirt v0.0.0-20220804181439-8648fbde413e
@@ -723,7 +727,7 @@ github.com/klauspost/compress/internal/cpuinfo
 github.com/klauspost/compress/internal/snapref
 github.com/klauspost/compress/zstd
 github.com/klauspost/compress/zstd/internal/xxhash
-# github.com/klauspost/cpuid/v2 v2.2.5
+# github.com/klauspost/cpuid/v2 v2.2.6
 ## explicit; go 1.15
 github.com/klauspost/cpuid/v2
 # github.com/klauspost/pgzip v1.2.6
@@ -761,6 +765,9 @@ github.com/mailru/easyjson/jwriter
 github.com/manifoldco/promptui
 github.com/manifoldco/promptui/list
 github.com/manifoldco/promptui/screenbuf
+# github.com/mattn/go-colorable v0.1.13
+## explicit; go 1.15
+github.com/mattn/go-colorable
 # github.com/mattn/go-isatty v0.0.19
 ## explicit; go 1.15
 github.com/mattn/go-isatty
@@ -930,7 +937,7 @@ github.com/pkg/errors
 ## explicit; go 1.15
 github.com/pkg/sftp
 github.com/pkg/sftp/internal/encoding/ssh/filexfer
-# github.com/pmezard/go-difflib v1.0.0
+# github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2
 ## explicit
 github.com/pmezard/go-difflib/difflib
 # github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c
@@ -1369,6 +1376,9 @@ gopkg.in/go-jose/go-jose.v2/json
 # gopkg.in/inf.v0 v0.9.1
 ## explicit
 gopkg.in/inf.v0
+# gopkg.in/natefinch/lumberjack.v2 v2.2.1
+## explicit; go 1.13
+gopkg.in/natefinch/lumberjack.v2
 # gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7
 ## explicit
 gopkg.in/tomb.v1