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
[](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
+[](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
+
+[](https://github.com/mattn/go-colorable/actions?query=workflow%3Atest)
+[](https://codecov.io/gh/mattn/go-colorable)
+[](http://godoc.org/github.com/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!
+
+
+
+
+## So Good!
+
+
+
+## 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 [](https://godoc.org/gopkg.in/natefinch/lumberjack.v2) [](https://travis-ci.org/natefinch/lumberjack) [](https://ci.appveyor.com/project/natefinch/lumberjack) [](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