mirror of
https://github.com/cheat/cheat.git
synced 2026-05-27 19:48:44 +02:00
chore(deps): bump github.com/go-git/go-billy/v5 from 5.7.0 to 5.9.0
Bumps [github.com/go-git/go-billy/v5](https://github.com/go-git/go-billy) from 5.7.0 to 5.9.0. - [Release notes](https://github.com/go-git/go-billy/releases) - [Commits](https://github.com/go-git/go-billy/compare/v5.7.0...v5.9.0) --- updated-dependencies: - dependency-name: github.com/go-git/go-billy/v5 dependency-version: 5.9.0 dependency-type: indirect ... Signed-off-by: dependabot[bot] <support@github.com>
This commit is contained in:
@@ -21,7 +21,7 @@ require (
|
|||||||
github.com/dlclark/regexp2 v1.11.5 // indirect
|
github.com/dlclark/regexp2 v1.11.5 // indirect
|
||||||
github.com/emirpasic/gods v1.18.1 // indirect
|
github.com/emirpasic/gods v1.18.1 // indirect
|
||||||
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
|
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
|
||||||
github.com/go-git/go-billy/v5 v5.7.0 // indirect
|
github.com/go-git/go-billy/v5 v5.9.0 // indirect
|
||||||
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect
|
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect
|
||||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
|
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
|
||||||
@@ -32,8 +32,8 @@ require (
|
|||||||
github.com/skeema/knownhosts v1.3.2 // indirect
|
github.com/skeema/knownhosts v1.3.2 // indirect
|
||||||
github.com/spf13/pflag v1.0.9 // indirect
|
github.com/spf13/pflag v1.0.9 // indirect
|
||||||
github.com/xanzy/ssh-agent v0.3.3 // indirect
|
github.com/xanzy/ssh-agent v0.3.3 // indirect
|
||||||
golang.org/x/crypto v0.48.0 // indirect
|
golang.org/x/crypto v0.50.0 // indirect
|
||||||
golang.org/x/net v0.50.0 // indirect
|
golang.org/x/net v0.53.0 // indirect
|
||||||
golang.org/x/sys v0.41.0 // indirect
|
golang.org/x/sys v0.43.0 // indirect
|
||||||
gopkg.in/warnings.v0 v0.1.2 // indirect
|
gopkg.in/warnings.v0 v0.1.2 // indirect
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -33,8 +33,8 @@ github.com/gliderlabs/ssh v0.3.8 h1:a4YXD1V7xMF9g5nTkdfnja3Sxy1PVDCj1Zg4Wb8vY6c=
|
|||||||
github.com/gliderlabs/ssh v0.3.8/go.mod h1:xYoytBv1sV0aL3CavoDuJIQNURXkkfPA/wxQ1pL1fAU=
|
github.com/gliderlabs/ssh v0.3.8/go.mod h1:xYoytBv1sV0aL3CavoDuJIQNURXkkfPA/wxQ1pL1fAU=
|
||||||
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI=
|
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI=
|
||||||
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic=
|
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic=
|
||||||
github.com/go-git/go-billy/v5 v5.7.0 h1:83lBUJhGWhYp0ngzCMSgllhUSuoHP1iEWYjsPl9nwqM=
|
github.com/go-git/go-billy/v5 v5.9.0 h1:jItGXszUDRtR/AlferWPTMN4j38BQ88XnXKbilmmBPA=
|
||||||
github.com/go-git/go-billy/v5 v5.7.0/go.mod h1:/1IUejTKH8xipsAcdfcSAlUlo2J7lkYV8GTKxAT/L3E=
|
github.com/go-git/go-billy/v5 v5.9.0/go.mod h1:jCnQMLj9eUgGU7+ludSTYoZL/GGmii14RxKFj7ROgHw=
|
||||||
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4=
|
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4=
|
||||||
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII=
|
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII=
|
||||||
github.com/go-git/go-git/v5 v5.16.5 h1:mdkuqblwr57kVfXri5TTH+nMFLNUxIj9Z7F5ykFbw5s=
|
github.com/go-git/go-git/v5 v5.16.5 h1:mdkuqblwr57kVfXri5TTH+nMFLNUxIj9Z7F5ykFbw5s=
|
||||||
@@ -93,13 +93,13 @@ github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM
|
|||||||
github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw=
|
github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw=
|
||||||
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
|
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
|
||||||
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||||
golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts=
|
golang.org/x/crypto v0.50.0 h1:zO47/JPrL6vsNkINmLoo/PH1gcxpls50DNogFvB5ZGI=
|
||||||
golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos=
|
golang.org/x/crypto v0.50.0/go.mod h1:3muZ7vA7PBCE6xgPX7nkzzjiUq87kRItoJQM1Yo8S+Q=
|
||||||
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8=
|
golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f h1:W3F4c+6OLc6H2lb//N1q4WpJkhzJCK5J6kUi1NTVXfM=
|
||||||
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY=
|
golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f/go.mod h1:J1xhfL/vlindoeF/aINzNzt2Bket5bjo9sdOYzOsU80=
|
||||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.50.0 h1:ucWh9eiCGyDR3vtzso0WMQinm2Dnt8cFMuQa9K33J60=
|
golang.org/x/net v0.53.0 h1:d+qAbo5L0orcWAr0a9JweQpjXF19LMXJE8Ey7hwOdUA=
|
||||||
golang.org/x/net v0.50.0/go.mod h1:UgoSli3F/pBgdJBHCTc+tp3gmrU4XswgGRgtnwWTfyM=
|
golang.org/x/net v0.53.0/go.mod h1:JvMuJH7rrdiCfbeHoo3fCQU24Lf5JJwT9W3sJFulfgs=
|
||||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
@@ -107,14 +107,14 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/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-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k=
|
golang.org/x/sys v0.43.0 h1:Rlag2XtaFTxp19wS8MXlJwTvoh8ArU6ezoyFsMyCTNI=
|
||||||
golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
golang.org/x/sys v0.43.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.40.0 h1:36e4zGLqU4yhjlmxEaagx2KuYbJq3EwY8K943ZsHcvg=
|
golang.org/x/term v0.42.0 h1:UiKe+zDFmJobeJ5ggPwOshJIVt6/Ft0rcfrXZDLWAWY=
|
||||||
golang.org/x/term v0.40.0/go.mod h1:w2P8uVp06p2iyKKuvXIm7N/y0UCRt3UfJTfZ7oOpglM=
|
golang.org/x/term v0.42.0/go.mod h1:Dq/D+snpsbazcBG5+F9Q1n2rXV8Ma+71xEjTRufARgY=
|
||||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.34.0 h1:oL/Qq0Kdaqxa1KbNeMKwQq0reLCCaFtqu2eNuSeNHbk=
|
golang.org/x/text v0.36.0 h1:JfKh3XmcRPqZPKevfXVpI1wXPTqbkE5f7JA92a55Yxg=
|
||||||
golang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA=
|
golang.org/x/text v0.36.0/go.mod h1:NIdBknypM8iqVmPiuco0Dh6P5Jcdk8lJL0CUebqK164=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
|||||||
+4
@@ -5,6 +5,10 @@ Billy implements an interface based on the `os` standard library, allowing to de
|
|||||||
|
|
||||||
Billy was born as part of [go-git/go-git](https://github.com/go-git/go-git) project.
|
Billy was born as part of [go-git/go-git](https://github.com/go-git/go-git) project.
|
||||||
|
|
||||||
|
## Version support
|
||||||
|
|
||||||
|
go-billy v5 is in maintenance mode. Users should upgrade to [go-billy v6](https://pkg.go.dev/github.com/go-git/go-billy/v6) where possible.
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
```go
|
```go
|
||||||
|
|||||||
+198
-10
@@ -3,19 +3,25 @@ package chroot
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"os"
|
"os"
|
||||||
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
"syscall"
|
||||||
|
|
||||||
"github.com/go-git/go-billy/v5"
|
"github.com/go-git/go-billy/v5"
|
||||||
"github.com/go-git/go-billy/v5/helper/polyfill"
|
"github.com/go-git/go-billy/v5/helper/polyfill"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ChrootHelper is a helper to implement billy.Chroot.
|
// ChrootHelper is a helper to implement billy.Chroot.
|
||||||
|
// It is not a security boundary, callers that need containment should use a
|
||||||
|
// filesystem implementation that enforces paths at the OS boundary instead.
|
||||||
type ChrootHelper struct {
|
type ChrootHelper struct {
|
||||||
underlying billy.Filesystem
|
underlying billy.Filesystem
|
||||||
base string
|
base string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const maxFollowedSymlinks = 8 // Aligns with POSIX_SYMLOOP_MAX
|
||||||
|
|
||||||
// New creates a new filesystem wrapping up the given 'fs'.
|
// New creates a new filesystem wrapping up the given 'fs'.
|
||||||
// The created filesystem has its base in the given ChrootHelperectory of the
|
// The created filesystem has its base in the given ChrootHelperectory of the
|
||||||
// underlying filesystem.
|
// underlying filesystem.
|
||||||
@@ -34,15 +40,184 @@ func (fs *ChrootHelper) underlyingPath(filename string) (string, error) {
|
|||||||
return fs.Join(fs.Root(), filename), nil
|
return fs.Join(fs.Root(), filename), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func isCrossBoundaries(path string) bool {
|
func (fs *ChrootHelper) followedPath(filename string, followFinal bool, op string) (string, error) {
|
||||||
path = filepath.ToSlash(path)
|
fullpath, err := fs.underlyingPath(filename)
|
||||||
path = filepath.Clean(path)
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
return strings.HasPrefix(path, ".."+string(filepath.Separator))
|
sl, ok := fs.underlying.(billy.Symlink)
|
||||||
|
if !ok {
|
||||||
|
return fullpath, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
rel, err := fs.relativeToRoot(fullpath)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
fullpath, err = fs.resolveFollowedPath(rel, followFinal, op, sl)
|
||||||
|
if errors.Is(err, billy.ErrNotSupported) {
|
||||||
|
return fs.underlyingPath(filename)
|
||||||
|
}
|
||||||
|
|
||||||
|
return fullpath, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fs *ChrootHelper) resolveFollowedPath(rel string, followFinal bool, op string, sl billy.Symlink) (string, error) {
|
||||||
|
if rel == "" {
|
||||||
|
return fs.resolveFollowedRoot(followFinal, op, sl)
|
||||||
|
}
|
||||||
|
|
||||||
|
parts := splitRelativePath(rel)
|
||||||
|
resolved := ""
|
||||||
|
followed := 0
|
||||||
|
|
||||||
|
for len(parts) > 0 {
|
||||||
|
part := parts[0]
|
||||||
|
parts = parts[1:]
|
||||||
|
|
||||||
|
currentRel := joinRelativePath(resolved, part)
|
||||||
|
currentPath := fs.Join(fs.Root(), currentRel)
|
||||||
|
if len(parts) == 0 && !followFinal {
|
||||||
|
return currentPath, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
fi, err := sl.Lstat(currentPath)
|
||||||
|
if err != nil {
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
return fs.Join(fs.Root(), joinRelativePath(append([]string{currentRel}, parts...)...)), nil
|
||||||
|
}
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
if fi.Mode()&os.ModeSymlink == 0 {
|
||||||
|
resolved = currentRel
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
followed++
|
||||||
|
if followed > maxFollowedSymlinks {
|
||||||
|
return "", symlinkLoopError(op, currentPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
target, err := sl.Readlink(currentPath)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
targetRel, err := fs.linkTargetRel(currentPath, target)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
if targetRel == currentRel {
|
||||||
|
return "", symlinkLoopError(op, currentPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
parts = append(splitRelativePath(targetRel), parts...)
|
||||||
|
resolved = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
return fs.Join(fs.Root(), resolved), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func symlinkLoopError(op, path string) error {
|
||||||
|
return &os.PathError{Op: op, Path: path, Err: syscall.ELOOP}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fs *ChrootHelper) resolveFollowedRoot(followFinal bool, op string, sl billy.Symlink) (string, error) {
|
||||||
|
root := fs.Join(fs.Root(), "")
|
||||||
|
if !followFinal {
|
||||||
|
return root, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
fi, err := sl.Lstat(root)
|
||||||
|
if err != nil {
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
return root, nil
|
||||||
|
}
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
if fi.Mode()&os.ModeSymlink == 0 {
|
||||||
|
return root, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
target, err := sl.Readlink(root)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
targetRel, err := fs.linkTargetRel(root, target)
|
||||||
|
if err != nil {
|
||||||
|
return root, err
|
||||||
|
}
|
||||||
|
if targetRel == "" {
|
||||||
|
return "", symlinkLoopError(op, root)
|
||||||
|
}
|
||||||
|
|
||||||
|
return fs.resolveFollowedPath(targetRel, followFinal, op, sl)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fs *ChrootHelper) relativeToRoot(filename string) (string, error) {
|
||||||
|
rel, err := filepath.Rel(filepath.Clean(fs.Root()), filepath.Clean(filename))
|
||||||
|
if err != nil || isCrossBoundaries(rel) {
|
||||||
|
return "", billy.ErrCrossedBoundary
|
||||||
|
}
|
||||||
|
|
||||||
|
if rel == "." {
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
return rel, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fs *ChrootHelper) linkTargetRel(linkPath, target string) (string, error) {
|
||||||
|
target = filepath.FromSlash(target)
|
||||||
|
if filepath.IsAbs(target) || strings.HasPrefix(target, string(filepath.Separator)) {
|
||||||
|
return fs.relativeToRoot(target)
|
||||||
|
}
|
||||||
|
|
||||||
|
return fs.relativeToRoot(fs.Join(filepath.Dir(linkPath), target))
|
||||||
|
}
|
||||||
|
|
||||||
|
func splitRelativePath(filename string) []string {
|
||||||
|
filename = filepath.Clean(filename)
|
||||||
|
if filename == "" || filename == "." {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return strings.Split(filepath.ToSlash(filename), "/")
|
||||||
|
}
|
||||||
|
|
||||||
|
func joinRelativePath(elem ...string) string {
|
||||||
|
parts := make([]string, 0, len(elem))
|
||||||
|
for _, part := range elem {
|
||||||
|
if part == "" || part == "." {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
parts = append(parts, part)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(parts) == 0 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return filepath.Join(parts...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func isCreateExclusive(flag int) bool {
|
||||||
|
return flag&os.O_CREATE != 0 && flag&os.O_EXCL != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func isCrossBoundaries(name string) bool {
|
||||||
|
name = filepath.ToSlash(name)
|
||||||
|
name = strings.TrimLeft(name, "/")
|
||||||
|
name = path.Clean(name)
|
||||||
|
|
||||||
|
return name == ".." || strings.HasPrefix(name, "../")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fs *ChrootHelper) Create(filename string) (billy.File, error) {
|
func (fs *ChrootHelper) Create(filename string) (billy.File, error) {
|
||||||
fullpath, err := fs.underlyingPath(filename)
|
fullpath, err := fs.followedPath(filename, true, "create")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -56,7 +231,7 @@ func (fs *ChrootHelper) Create(filename string) (billy.File, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (fs *ChrootHelper) Open(filename string) (billy.File, error) {
|
func (fs *ChrootHelper) Open(filename string) (billy.File, error) {
|
||||||
fullpath, err := fs.underlyingPath(filename)
|
fullpath, err := fs.followedPath(filename, true, "open")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -70,7 +245,7 @@ func (fs *ChrootHelper) Open(filename string) (billy.File, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (fs *ChrootHelper) OpenFile(filename string, flag int, mode os.FileMode) (billy.File, error) {
|
func (fs *ChrootHelper) OpenFile(filename string, flag int, mode os.FileMode) (billy.File, error) {
|
||||||
fullpath, err := fs.underlyingPath(filename)
|
fullpath, err := fs.followedPath(filename, !isCreateExclusive(flag), "open")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -84,12 +259,16 @@ func (fs *ChrootHelper) OpenFile(filename string, flag int, mode os.FileMode) (b
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (fs *ChrootHelper) Stat(filename string) (os.FileInfo, error) {
|
func (fs *ChrootHelper) Stat(filename string) (os.FileInfo, error) {
|
||||||
fullpath, err := fs.underlyingPath(filename)
|
fullpath, err := fs.followedPath(filename, true, "stat")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return fs.underlying.Stat(fullpath)
|
fi, err := fs.underlying.Stat(fullpath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return fileInfo{FileInfo: fi, name: filepath.Base(filename)}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fs *ChrootHelper) Rename(from, to string) error {
|
func (fs *ChrootHelper) Rename(from, to string) error {
|
||||||
@@ -135,7 +314,7 @@ func (fs *ChrootHelper) TempFile(dir, prefix string) (billy.File, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (fs *ChrootHelper) ReadDir(path string) ([]os.FileInfo, error) {
|
func (fs *ChrootHelper) ReadDir(path string) ([]os.FileInfo, error) {
|
||||||
fullpath, err := fs.underlyingPath(path)
|
fullpath, err := fs.followedPath(path, true, "readdir")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -241,6 +420,11 @@ type file struct {
|
|||||||
name string
|
name string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type fileInfo struct {
|
||||||
|
os.FileInfo
|
||||||
|
name string
|
||||||
|
}
|
||||||
|
|
||||||
func newFile(fs billy.Filesystem, f billy.File, filename string) billy.File {
|
func newFile(fs billy.Filesystem, f billy.File, filename string) billy.File {
|
||||||
filename = fs.Join(fs.Root(), filename)
|
filename = fs.Join(fs.Root(), filename)
|
||||||
filename, _ = filepath.Rel(fs.Root(), filename)
|
filename, _ = filepath.Rel(fs.Root(), filename)
|
||||||
@@ -254,3 +438,7 @@ func newFile(fs billy.Filesystem, f billy.File, filename string) billy.File {
|
|||||||
func (f *file) Name() string {
|
func (f *file) Name() string {
|
||||||
return f.name
|
return f.name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (fi fileInfo) Name() string {
|
||||||
|
return fi.name
|
||||||
|
}
|
||||||
|
|||||||
+10
-1
@@ -13,7 +13,7 @@ type Polyfill struct {
|
|||||||
c capabilities
|
c capabilities
|
||||||
}
|
}
|
||||||
|
|
||||||
type capabilities struct{ tempfile, dir, symlink, chroot bool }
|
type capabilities struct{ tempfile, dir, symlink, chroot, chmod bool }
|
||||||
|
|
||||||
// New creates a new filesystem wrapping up 'fs' the intercepts all the calls
|
// New creates a new filesystem wrapping up 'fs' the intercepts all the calls
|
||||||
// made and errors if fs doesn't implement any of the billy interfaces.
|
// made and errors if fs doesn't implement any of the billy interfaces.
|
||||||
@@ -28,6 +28,7 @@ func New(fs billy.Basic) billy.Filesystem {
|
|||||||
_, h.c.dir = h.Basic.(billy.Dir)
|
_, h.c.dir = h.Basic.(billy.Dir)
|
||||||
_, h.c.symlink = h.Basic.(billy.Symlink)
|
_, h.c.symlink = h.Basic.(billy.Symlink)
|
||||||
_, h.c.chroot = h.Basic.(billy.Chroot)
|
_, h.c.chroot = h.Basic.(billy.Chroot)
|
||||||
|
_, h.c.chmod = h.Basic.(billy.Chmod)
|
||||||
return h
|
return h
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,6 +88,14 @@ func (h *Polyfill) Chroot(path string) (billy.Filesystem, error) {
|
|||||||
return h.Basic.(billy.Chroot).Chroot(path)
|
return h.Basic.(billy.Chroot).Chroot(path)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (h *Polyfill) Chmod(path string, mode os.FileMode) error {
|
||||||
|
if !h.c.chmod {
|
||||||
|
return billy.ErrNotSupported
|
||||||
|
}
|
||||||
|
|
||||||
|
return h.Basic.(billy.Chmod).Chmod(path, mode)
|
||||||
|
}
|
||||||
|
|
||||||
func (h *Polyfill) Root() string {
|
func (h *Polyfill) Root() string {
|
||||||
if !h.c.chroot {
|
if !h.c.chroot {
|
||||||
return string(filepath.Separator)
|
return string(filepath.Separator)
|
||||||
|
|||||||
+5
@@ -24,6 +24,9 @@ var Default = &ChrootOS{}
|
|||||||
// New returns a new OS filesystem.
|
// New returns a new OS filesystem.
|
||||||
// By default paths are deduplicated, but still enforced
|
// By default paths are deduplicated, but still enforced
|
||||||
// under baseDir. For more info refer to WithDeduplicatePath.
|
// under baseDir. For more info refer to WithDeduplicatePath.
|
||||||
|
//
|
||||||
|
// New returns ChrootOS by default for v5 compatibility. Users should prefer
|
||||||
|
// New with WithBoundOS.
|
||||||
func New(baseDir string, opts ...Option) billy.Filesystem {
|
func New(baseDir string, opts ...Option) billy.Filesystem {
|
||||||
o := &options{
|
o := &options{
|
||||||
deduplicatePath: true,
|
deduplicatePath: true,
|
||||||
@@ -47,6 +50,8 @@ func WithBoundOS() Option {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// WithChrootOS returns the option of using a Chroot filesystem OS.
|
// WithChrootOS returns the option of using a Chroot filesystem OS.
|
||||||
|
//
|
||||||
|
// Deprecated: use WithBoundOS instead.
|
||||||
func WithChrootOS() Option {
|
func WithChrootOS() Option {
|
||||||
return func(o *options) {
|
return func(o *options) {
|
||||||
o.Type = ChrootOSFS
|
o.Type = ChrootOSFS
|
||||||
|
|||||||
+93
-15
@@ -20,6 +20,7 @@
|
|||||||
package osfs
|
package osfs
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
@@ -29,6 +30,31 @@ import (
|
|||||||
"github.com/go-git/go-billy/v5"
|
"github.com/go-git/go-billy/v5"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// ErrBaseDirCannotBeRemoved is returned when removing the BoundOS base dir.
|
||||||
|
ErrBaseDirCannotBeRemoved = errors.New("base dir cannot be removed")
|
||||||
|
|
||||||
|
// ErrBaseDirCannotBeRenamed is returned when renaming the BoundOS base dir.
|
||||||
|
ErrBaseDirCannotBeRenamed = errors.New("base dir cannot be renamed")
|
||||||
|
|
||||||
|
dotPrefixes = dotPathPrefixes()
|
||||||
|
dotSeparators = dotPathSeparators()
|
||||||
|
)
|
||||||
|
|
||||||
|
func dotPathPrefixes() []string {
|
||||||
|
if filepath.Separator == '\\' {
|
||||||
|
return []string{"./", ".\\"}
|
||||||
|
}
|
||||||
|
return []string{"./"}
|
||||||
|
}
|
||||||
|
|
||||||
|
func dotPathSeparators() string {
|
||||||
|
if filepath.Separator == '\\' {
|
||||||
|
return `/\`
|
||||||
|
}
|
||||||
|
return `/`
|
||||||
|
}
|
||||||
|
|
||||||
// BoundOS is a fs implementation based on the OS filesystem which is bound to
|
// BoundOS is a fs implementation based on the OS filesystem which is bound to
|
||||||
// a base dir.
|
// a base dir.
|
||||||
// Prefer this fs implementation over ChrootOS.
|
// Prefer this fs implementation over ChrootOS.
|
||||||
@@ -54,6 +80,7 @@ func (fs *BoundOS) Create(filename string) (billy.File, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (fs *BoundOS) OpenFile(filename string, flag int, perm os.FileMode) (billy.File, error) {
|
func (fs *BoundOS) OpenFile(filename string, flag int, perm os.FileMode) (billy.File, error) {
|
||||||
|
filename = fs.expandDot(filename)
|
||||||
fn, err := fs.abs(filename)
|
fn, err := fs.abs(filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -62,6 +89,7 @@ func (fs *BoundOS) OpenFile(filename string, flag int, perm os.FileMode) (billy.
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (fs *BoundOS) ReadDir(path string) ([]os.FileInfo, error) {
|
func (fs *BoundOS) ReadDir(path string) ([]os.FileInfo, error) {
|
||||||
|
path = fs.expandDot(path)
|
||||||
dir, err := fs.abs(path)
|
dir, err := fs.abs(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -71,6 +99,12 @@ func (fs *BoundOS) ReadDir(path string) ([]os.FileInfo, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (fs *BoundOS) Rename(from, to string) error {
|
func (fs *BoundOS) Rename(from, to string) error {
|
||||||
|
if fs.isBaseDir(from) {
|
||||||
|
return ErrBaseDirCannotBeRenamed
|
||||||
|
}
|
||||||
|
from = fs.expandDot(from)
|
||||||
|
to = fs.expandDot(to)
|
||||||
|
|
||||||
f, err := fs.abs(from)
|
f, err := fs.abs(from)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -89,6 +123,7 @@ func (fs *BoundOS) Rename(from, to string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (fs *BoundOS) MkdirAll(path string, perm os.FileMode) error {
|
func (fs *BoundOS) MkdirAll(path string, perm os.FileMode) error {
|
||||||
|
path = fs.expandDot(path)
|
||||||
dir, err := fs.abs(path)
|
dir, err := fs.abs(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -101,6 +136,7 @@ func (fs *BoundOS) Open(filename string) (billy.File, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (fs *BoundOS) Stat(filename string) (os.FileInfo, error) {
|
func (fs *BoundOS) Stat(filename string) (os.FileInfo, error) {
|
||||||
|
filename = fs.expandDot(filename)
|
||||||
filename, err := fs.abs(filename)
|
filename, err := fs.abs(filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -109,6 +145,11 @@ func (fs *BoundOS) Stat(filename string) (os.FileInfo, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (fs *BoundOS) Remove(filename string) error {
|
func (fs *BoundOS) Remove(filename string) error {
|
||||||
|
if fs.isBaseDir(filename) {
|
||||||
|
return ErrBaseDirCannotBeRemoved
|
||||||
|
}
|
||||||
|
filename = fs.expandDot(filename)
|
||||||
|
|
||||||
fn, err := fs.abs(filename)
|
fn, err := fs.abs(filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -122,10 +163,19 @@ func (fs *BoundOS) Remove(filename string) error {
|
|||||||
func (fs *BoundOS) TempFile(dir, prefix string) (billy.File, error) {
|
func (fs *BoundOS) TempFile(dir, prefix string) (billy.File, error) {
|
||||||
if dir != "" {
|
if dir != "" {
|
||||||
var err error
|
var err error
|
||||||
|
dir = fs.expandDot(dir)
|
||||||
dir, err = fs.abs(dir)
|
dir, err = fs.abs(dir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_, err = os.Stat(dir)
|
||||||
|
if err != nil && os.IsNotExist(err) {
|
||||||
|
err = os.MkdirAll(dir, defaultDirectoryMode)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return tempFile(dir, prefix)
|
return tempFile(dir, prefix)
|
||||||
@@ -136,6 +186,11 @@ func (fs *BoundOS) Join(elem ...string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (fs *BoundOS) RemoveAll(path string) error {
|
func (fs *BoundOS) RemoveAll(path string) error {
|
||||||
|
if fs.isBaseDir(path) {
|
||||||
|
return ErrBaseDirCannotBeRemoved
|
||||||
|
}
|
||||||
|
path = fs.expandDot(path)
|
||||||
|
|
||||||
dir, err := fs.abs(path)
|
dir, err := fs.abs(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -144,6 +199,7 @@ func (fs *BoundOS) RemoveAll(path string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (fs *BoundOS) Symlink(target, link string) error {
|
func (fs *BoundOS) Symlink(target, link string) error {
|
||||||
|
link = fs.expandDot(link)
|
||||||
ln, err := fs.abs(link)
|
ln, err := fs.abs(link)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -156,6 +212,7 @@ func (fs *BoundOS) Symlink(target, link string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (fs *BoundOS) Lstat(filename string) (os.FileInfo, error) {
|
func (fs *BoundOS) Lstat(filename string) (os.FileInfo, error) {
|
||||||
|
filename = fs.expandDot(filename)
|
||||||
filename = filepath.Clean(filename)
|
filename = filepath.Clean(filename)
|
||||||
if !filepath.IsAbs(filename) {
|
if !filepath.IsAbs(filename) {
|
||||||
filename = filepath.Join(fs.baseDir, filename)
|
filename = filepath.Join(fs.baseDir, filename)
|
||||||
@@ -167,6 +224,7 @@ func (fs *BoundOS) Lstat(filename string) (os.FileInfo, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (fs *BoundOS) Readlink(link string) (string, error) {
|
func (fs *BoundOS) Readlink(link string) (string, error) {
|
||||||
|
link = fs.expandDot(link)
|
||||||
if !filepath.IsAbs(link) {
|
if !filepath.IsAbs(link) {
|
||||||
link = filepath.Clean(filepath.Join(fs.baseDir, link))
|
link = filepath.Clean(filepath.Join(fs.baseDir, link))
|
||||||
}
|
}
|
||||||
@@ -177,6 +235,7 @@ func (fs *BoundOS) Readlink(link string) (string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (fs *BoundOS) Chmod(path string, mode os.FileMode) error {
|
func (fs *BoundOS) Chmod(path string, mode os.FileMode) error {
|
||||||
|
path = fs.expandDot(path)
|
||||||
abspath, err := fs.abs(path)
|
abspath, err := fs.abs(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -191,7 +250,7 @@ func (fs *BoundOS) Chroot(path string) (billy.Filesystem, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return New(joined), nil
|
return New(joined, WithBoundOS()), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Root returns the current base dir of the billy.Filesystem.
|
// Root returns the current base dir of the billy.Filesystem.
|
||||||
@@ -212,6 +271,37 @@ func (fs *BoundOS) createDir(fullpath string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (fs *BoundOS) expandDot(path string) string {
|
||||||
|
if path == "." {
|
||||||
|
return fs.baseDir
|
||||||
|
}
|
||||||
|
for _, prefix := range dotPrefixes {
|
||||||
|
if strings.HasPrefix(path, prefix) {
|
||||||
|
path = strings.TrimLeft(strings.TrimPrefix(path, prefix), dotSeparators)
|
||||||
|
if path == "" {
|
||||||
|
return fs.baseDir
|
||||||
|
}
|
||||||
|
return path
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return path
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fs *BoundOS) isBaseDir(path string) bool {
|
||||||
|
if path == "" || filepath.Clean(path) == "." {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
path = fs.expandDot(path)
|
||||||
|
if filepath.Clean(path) == filepath.Clean(fs.baseDir) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
abspath, err := fs.abs(path)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return filepath.Clean(abspath) == filepath.Clean(fs.baseDir)
|
||||||
|
}
|
||||||
|
|
||||||
// abs transforms filename to an absolute path, taking into account the base dir.
|
// abs transforms filename to an absolute path, taking into account the base dir.
|
||||||
// Relative paths won't be allowed to ascend the base dir, so `../file` will become
|
// Relative paths won't be allowed to ascend the base dir, so `../file` will become
|
||||||
// `/working-dir/file`.
|
// `/working-dir/file`.
|
||||||
@@ -225,7 +315,7 @@ func (fs *BoundOS) abs(filename string) (string, error) {
|
|||||||
|
|
||||||
path, err := securejoin.SecureJoin(fs.baseDir, filename)
|
path, err := securejoin.SecureJoin(fs.baseDir, filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", nil
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
if fs.deduplicatePath {
|
if fs.deduplicatePath {
|
||||||
@@ -238,24 +328,12 @@ func (fs *BoundOS) abs(filename string) (string, error) {
|
|||||||
return path, nil
|
return path, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// insideBaseDir checks whether filename is located within
|
|
||||||
// the fs.baseDir.
|
|
||||||
func (fs *BoundOS) insideBaseDir(filename string) (bool, error) {
|
|
||||||
if filename == fs.baseDir {
|
|
||||||
return true, nil
|
|
||||||
}
|
|
||||||
if !strings.HasPrefix(filename, fs.baseDir+string(filepath.Separator)) {
|
|
||||||
return false, fmt.Errorf("path outside base dir")
|
|
||||||
}
|
|
||||||
return true, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// insideBaseDirEval checks whether filename is contained within
|
// insideBaseDirEval checks whether filename is contained within
|
||||||
// a dir that is within the fs.baseDir, by first evaluating any symlinks
|
// a dir that is within the fs.baseDir, by first evaluating any symlinks
|
||||||
// that either filename or fs.baseDir may contain.
|
// that either filename or fs.baseDir may contain.
|
||||||
func (fs *BoundOS) insideBaseDirEval(filename string) (bool, error) {
|
func (fs *BoundOS) insideBaseDirEval(filename string) (bool, error) {
|
||||||
// "/" contains all others.
|
// "/" contains all others.
|
||||||
if fs.baseDir == "/" {
|
if fs.baseDir == "/" || fs.baseDir == filename {
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
dir, err := filepath.EvalSymlinks(filepath.Dir(filename))
|
dir, err := filepath.EvalSymlinks(filepath.Dir(filename))
|
||||||
|
|||||||
+10
@@ -14,6 +14,8 @@ import (
|
|||||||
// ChrootOS is a legacy filesystem based on a "soft chroot" of the os filesystem.
|
// ChrootOS is a legacy filesystem based on a "soft chroot" of the os filesystem.
|
||||||
// Although this is still the default os filesystem, consider using BoundOS instead.
|
// Although this is still the default os filesystem, consider using BoundOS instead.
|
||||||
//
|
//
|
||||||
|
// Deprecated: use New with WithBoundOS instead.
|
||||||
|
//
|
||||||
// Behaviours of note:
|
// Behaviours of note:
|
||||||
// 1. A "soft chroot" translates the base dir to "/" for the purposes of the
|
// 1. A "soft chroot" translates the base dir to "/" for the purposes of the
|
||||||
// fs abstraction.
|
// fs abstraction.
|
||||||
@@ -24,6 +26,14 @@ import (
|
|||||||
type ChrootOS struct{}
|
type ChrootOS struct{}
|
||||||
|
|
||||||
func newChrootOS(baseDir string) billy.Filesystem {
|
func newChrootOS(baseDir string) billy.Filesystem {
|
||||||
|
if baseDir != "" {
|
||||||
|
resolved, err := filepath.EvalSymlinks(baseDir)
|
||||||
|
if err != nil {
|
||||||
|
return chroot.New(&ChrootOS{}, baseDir)
|
||||||
|
}
|
||||||
|
baseDir = resolved
|
||||||
|
}
|
||||||
|
|
||||||
return chroot.New(&ChrootOS{}, baseDir)
|
return chroot.New(&ChrootOS{}, baseDir)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+19
-24
@@ -16,8 +16,6 @@ import (
|
|||||||
// can but returns the first error it encounters. If the path does not exist,
|
// can but returns the first error it encounters. If the path does not exist,
|
||||||
// RemoveAll returns nil (no error).
|
// RemoveAll returns nil (no error).
|
||||||
func RemoveAll(fs billy.Basic, path string) error {
|
func RemoveAll(fs billy.Basic, path string) error {
|
||||||
fs, path = getUnderlyingAndPath(fs, path)
|
|
||||||
|
|
||||||
if r, ok := fs.(removerAll); ok {
|
if r, ok := fs.(removerAll); ok {
|
||||||
return r.RemoveAll(path)
|
return r.RemoveAll(path)
|
||||||
}
|
}
|
||||||
@@ -39,7 +37,7 @@ func removeAll(fs billy.Basic, path string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise, is this a directory we need to recurse into?
|
// Otherwise, is this a directory we need to recurse into?
|
||||||
dir, serr := fs.Stat(path)
|
dir, serr := lstat(fs, path)
|
||||||
if serr != nil {
|
if serr != nil {
|
||||||
if errors.Is(serr, os.ErrNotExist) {
|
if errors.Is(serr, os.ErrNotExist) {
|
||||||
return nil
|
return nil
|
||||||
@@ -48,8 +46,8 @@ func removeAll(fs billy.Basic, path string) error {
|
|||||||
return serr
|
return serr
|
||||||
}
|
}
|
||||||
|
|
||||||
if !dir.IsDir() {
|
if dir.Mode()&os.ModeSymlink != 0 || !dir.IsDir() {
|
||||||
// Not a directory; return the error from Remove.
|
// Not a directory we should recurse into; return the error from Remove.
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -62,7 +60,7 @@ func removeAll(fs billy.Basic, path string) error {
|
|||||||
fis, err := dirfs.ReadDir(path)
|
fis, err := dirfs.ReadDir(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, os.ErrNotExist) {
|
if errors.Is(err, os.ErrNotExist) {
|
||||||
// Race. It was deleted between the Lstat and Open.
|
// Race. It was deleted between the Lstat and ReadDir.
|
||||||
// Return nil per RemoveAll's docs.
|
// Return nil per RemoveAll's docs.
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -91,7 +89,18 @@ func removeAll(fs billy.Basic, path string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return err
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func lstat(filesystem billy.Basic, path string) (os.FileInfo, error) {
|
||||||
|
if sl, ok := filesystem.(billy.Symlink); ok {
|
||||||
|
// Avoid following a symlink substituted after the initial Remove fails.
|
||||||
|
fi, err := sl.Lstat(path)
|
||||||
|
if err == nil || !errors.Is(err, billy.ErrNotSupported) {
|
||||||
|
return fi, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return filesystem.Stat(path)
|
||||||
}
|
}
|
||||||
|
|
||||||
// WriteFile writes data to a file named by filename in the given filesystem.
|
// WriteFile writes data to a file named by filename in the given filesystem.
|
||||||
@@ -123,8 +132,10 @@ func WriteFile(fs billy.Basic, filename string, data []byte, perm os.FileMode) (
|
|||||||
// We generate random temporary file names so that there's a good
|
// We generate random temporary file names so that there's a good
|
||||||
// chance the file doesn't exist yet - keeps the number of tries in
|
// chance the file doesn't exist yet - keeps the number of tries in
|
||||||
// TempFile to a minimum.
|
// TempFile to a minimum.
|
||||||
var rand uint32
|
var (
|
||||||
var randmu sync.Mutex
|
rand uint32
|
||||||
|
randmu sync.Mutex
|
||||||
|
)
|
||||||
|
|
||||||
func reseed() uint32 {
|
func reseed() uint32 {
|
||||||
return uint32(time.Now().UnixNano() + int64(os.Getpid()))
|
return uint32(time.Now().UnixNano() + int64(os.Getpid()))
|
||||||
@@ -220,22 +231,6 @@ func getTempDir(fs billy.Basic) string {
|
|||||||
return ".tmp"
|
return ".tmp"
|
||||||
}
|
}
|
||||||
|
|
||||||
type underlying interface {
|
|
||||||
Underlying() billy.Basic
|
|
||||||
}
|
|
||||||
|
|
||||||
func getUnderlyingAndPath(fs billy.Basic, path string) (billy.Basic, string) {
|
|
||||||
u, ok := fs.(underlying)
|
|
||||||
if !ok {
|
|
||||||
return fs, path
|
|
||||||
}
|
|
||||||
if ch, ok := fs.(billy.Chroot); ok {
|
|
||||||
path = fs.Join(ch.Root(), path)
|
|
||||||
}
|
|
||||||
|
|
||||||
return u.Underlying(), path
|
|
||||||
}
|
|
||||||
|
|
||||||
// ReadFile reads the named file and returns the contents from the given filesystem.
|
// ReadFile reads the named file and returns the contents from the given filesystem.
|
||||||
// A successful call returns err == nil, not err == EOF.
|
// A successful call returns err == nil, not err == EOF.
|
||||||
// Because ReadFile reads the whole file, it does not treat an EOF from Read
|
// Because ReadFile reads the whole file, it does not treat an EOF from Read
|
||||||
|
|||||||
+1
-1
@@ -36,7 +36,7 @@ func (s *server) processRequestBytes(reqData []byte) []byte {
|
|||||||
return []byte{agentFailure}
|
return []byte{agentFailure}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err == nil && rep == nil {
|
if rep == nil {
|
||||||
return []byte{agentSuccess}
|
return []byte{agentSuccess}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -586,7 +586,7 @@ func (c *cbcCipher) writeCipherPacket(seqNum uint32, w io.Writer, rand io.Reader
|
|||||||
|
|
||||||
// Length of encrypted portion of the packet (header, payload, padding).
|
// Length of encrypted portion of the packet (header, payload, padding).
|
||||||
// Enforce minimum padding and packet size.
|
// Enforce minimum padding and packet size.
|
||||||
encLength := maxUInt32(prefixLen+len(packet)+cbcMinPaddingSize, cbcMinPaddingSize)
|
encLength := maxUInt32(prefixLen+len(packet)+cbcMinPaddingSize, cbcMinPacketSize)
|
||||||
// Enforce block size.
|
// Enforce block size.
|
||||||
encLength = (encLength + effectiveBlockSize - 1) / effectiveBlockSize * effectiveBlockSize
|
encLength = (encLength + effectiveBlockSize - 1) / effectiveBlockSize * effectiveBlockSize
|
||||||
|
|
||||||
|
|||||||
+7
-3
@@ -274,10 +274,14 @@ func pickSignatureAlgorithm(signer Signer, extensions map[string][]byte) (MultiA
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Filter algorithms based on those supported by MultiAlgorithmSigner.
|
// Filter algorithms based on those supported by MultiAlgorithmSigner.
|
||||||
|
// Iterate over the signer's algorithms first to preserve its preference order.
|
||||||
|
supportedKeyAlgos := algorithmsForKeyFormat(keyFormat)
|
||||||
var keyAlgos []string
|
var keyAlgos []string
|
||||||
for _, algo := range algorithmsForKeyFormat(keyFormat) {
|
for _, signerAlgo := range as.Algorithms() {
|
||||||
if slices.Contains(as.Algorithms(), underlyingAlgo(algo)) {
|
if idx := slices.IndexFunc(supportedKeyAlgos, func(algo string) bool {
|
||||||
keyAlgos = append(keyAlgos, algo)
|
return underlyingAlgo(algo) == signerAlgo
|
||||||
|
}); idx >= 0 {
|
||||||
|
keyAlgos = append(keyAlgos, supportedKeyAlgos[idx])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+12
@@ -0,0 +1,12 @@
|
|||||||
|
// Copyright 2024 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
//go:build darwin && arm64 && gc
|
||||||
|
|
||||||
|
#include "textflag.h"
|
||||||
|
|
||||||
|
TEXT libc_sysctlbyname_trampoline<>(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_sysctlbyname(SB)
|
||||||
|
GLOBL ·libc_sysctlbyname_trampoline_addr(SB), RODATA, $8
|
||||||
|
DATA ·libc_sysctlbyname_trampoline_addr(SB)/8, $libc_sysctlbyname_trampoline<>(SB)
|
||||||
+3
-6
@@ -44,14 +44,11 @@ func initOptions() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func archInit() {
|
func archInit() {
|
||||||
switch runtime.GOOS {
|
if runtime.GOOS == "freebsd" {
|
||||||
case "freebsd":
|
|
||||||
readARM64Registers()
|
readARM64Registers()
|
||||||
case "linux", "netbsd", "openbsd", "windows":
|
} else {
|
||||||
|
// Most platforms don't seem to allow directly reading these registers.
|
||||||
doinit()
|
doinit()
|
||||||
default:
|
|
||||||
// Many platforms don't seem to allow reading these registers.
|
|
||||||
setMinimalFeatures()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+67
@@ -0,0 +1,67 @@
|
|||||||
|
// Copyright 2026 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
//go:build darwin && arm64 && gc
|
||||||
|
|
||||||
|
package cpu
|
||||||
|
|
||||||
|
func doinit() {
|
||||||
|
setMinimalFeatures()
|
||||||
|
|
||||||
|
// The feature flags are explained in [Instruction Set Detection].
|
||||||
|
// There are some differences between MacOS versions:
|
||||||
|
//
|
||||||
|
// MacOS 11 and 12 do not have "hw.optional" sysctl values for some of the features.
|
||||||
|
//
|
||||||
|
// MacOS 13 changed some of the naming conventions to align with ARM Architecture Reference Manual.
|
||||||
|
// For example "hw.optional.armv8_2_sha512" became "hw.optional.arm.FEAT_SHA512".
|
||||||
|
// It currently checks both to stay compatible with MacOS 11 and 12.
|
||||||
|
// The old names also work with MacOS 13, however it's not clear whether
|
||||||
|
// they will continue working with future OS releases.
|
||||||
|
//
|
||||||
|
// Once MacOS 12 is no longer supported the old names can be removed.
|
||||||
|
//
|
||||||
|
// [Instruction Set Detection]: https://developer.apple.com/documentation/kernel/1387446-sysctlbyname/determining_instruction_set_characteristics
|
||||||
|
|
||||||
|
// Encryption, hashing and checksum capabilities
|
||||||
|
|
||||||
|
// For the following flags there are no MacOS 11 sysctl flags.
|
||||||
|
ARM64.HasAES = true || darwinSysctlEnabled([]byte("hw.optional.arm.FEAT_AES\x00"))
|
||||||
|
ARM64.HasPMULL = true || darwinSysctlEnabled([]byte("hw.optional.arm.FEAT_PMULL\x00"))
|
||||||
|
ARM64.HasSHA1 = true || darwinSysctlEnabled([]byte("hw.optional.arm.FEAT_SHA1\x00"))
|
||||||
|
ARM64.HasSHA2 = true || darwinSysctlEnabled([]byte("hw.optional.arm.FEAT_SHA256\x00"))
|
||||||
|
|
||||||
|
ARM64.HasSHA3 = darwinSysctlEnabled([]byte("hw.optional.armv8_2_sha3\x00")) || darwinSysctlEnabled([]byte("hw.optional.arm.FEAT_SHA3\x00"))
|
||||||
|
ARM64.HasSHA512 = darwinSysctlEnabled([]byte("hw.optional.armv8_2_sha512\x00")) || darwinSysctlEnabled([]byte("hw.optional.arm.FEAT_SHA512\x00"))
|
||||||
|
|
||||||
|
ARM64.HasCRC32 = darwinSysctlEnabled([]byte("hw.optional.armv8_crc32\x00"))
|
||||||
|
|
||||||
|
// Atomic and memory ordering
|
||||||
|
ARM64.HasATOMICS = darwinSysctlEnabled([]byte("hw.optional.armv8_1_atomics\x00")) || darwinSysctlEnabled([]byte("hw.optional.arm.FEAT_LSE\x00"))
|
||||||
|
ARM64.HasLRCPC = darwinSysctlEnabled([]byte("hw.optional.arm.FEAT_LRCPC\x00"))
|
||||||
|
|
||||||
|
// SIMD and floating point capabilities
|
||||||
|
ARM64.HasFPHP = darwinSysctlEnabled([]byte("hw.optional.neon_fp16\x00")) || darwinSysctlEnabled([]byte("hw.optional.arm.FEAT_FP16\x00"))
|
||||||
|
ARM64.HasASIMDHP = darwinSysctlEnabled([]byte("hw.optional.neon_hpfp\x00")) || darwinSysctlEnabled([]byte("hw.optional.AdvSIMD_HPFPCvt\x00"))
|
||||||
|
ARM64.HasASIMDRDM = darwinSysctlEnabled([]byte("hw.optional.arm.FEAT_RDM\x00"))
|
||||||
|
ARM64.HasASIMDDP = darwinSysctlEnabled([]byte("hw.optional.arm.FEAT_DotProd\x00"))
|
||||||
|
ARM64.HasASIMDFHM = darwinSysctlEnabled([]byte("hw.optional.armv8_2_fhm\x00")) || darwinSysctlEnabled([]byte("hw.optional.arm.FEAT_FHM\x00"))
|
||||||
|
ARM64.HasI8MM = darwinSysctlEnabled([]byte("hw.optional.arm.FEAT_I8MM\x00"))
|
||||||
|
|
||||||
|
ARM64.HasJSCVT = darwinSysctlEnabled([]byte("hw.optional.arm.FEAT_JSCVT\x00"))
|
||||||
|
ARM64.HasFCMA = darwinSysctlEnabled([]byte("hw.optional.armv8_3_compnum\x00")) || darwinSysctlEnabled([]byte("hw.optional.arm.FEAT_FCMA\x00"))
|
||||||
|
|
||||||
|
// Miscellaneous
|
||||||
|
ARM64.HasDCPOP = darwinSysctlEnabled([]byte("hw.optional.arm.FEAT_DPB\x00"))
|
||||||
|
ARM64.HasEVTSTRM = darwinSysctlEnabled([]byte("hw.optional.arm.FEAT_ECV\x00"))
|
||||||
|
ARM64.HasDIT = darwinSysctlEnabled([]byte("hw.optional.arm.FEAT_DIT\x00"))
|
||||||
|
|
||||||
|
// Not supported, but added for completeness
|
||||||
|
ARM64.HasCPUID = false
|
||||||
|
|
||||||
|
ARM64.HasSM3 = false // darwinSysctlEnabled([]byte("hw.optional.arm.FEAT_SM3\x00"))
|
||||||
|
ARM64.HasSM4 = false // darwinSysctlEnabled([]byte("hw.optional.arm.FEAT_SM4\x00"))
|
||||||
|
ARM64.HasSVE = false // darwinSysctlEnabled([]byte("hw.optional.arm.FEAT_SVE\x00"))
|
||||||
|
ARM64.HasSVE2 = false // darwinSysctlEnabled([]byte("hw.optional.arm.FEAT_SVE2\x00"))
|
||||||
|
}
|
||||||
+31
@@ -0,0 +1,31 @@
|
|||||||
|
// Copyright 2026 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
//go:build darwin && arm64 && !gc
|
||||||
|
|
||||||
|
package cpu
|
||||||
|
|
||||||
|
import "runtime"
|
||||||
|
|
||||||
|
func doinit() {
|
||||||
|
setMinimalFeatures()
|
||||||
|
|
||||||
|
ARM64.HasASIMD = true
|
||||||
|
ARM64.HasFP = true
|
||||||
|
|
||||||
|
// Go already assumes these to be available because they were on the M1
|
||||||
|
// and these are supported on all Apple arm64 chips.
|
||||||
|
ARM64.HasAES = true
|
||||||
|
ARM64.HasPMULL = true
|
||||||
|
ARM64.HasSHA1 = true
|
||||||
|
ARM64.HasSHA2 = true
|
||||||
|
|
||||||
|
if runtime.GOOS != "ios" {
|
||||||
|
// Apple A7 processors do not support these, however
|
||||||
|
// M-series SoCs are at least armv8.4-a
|
||||||
|
ARM64.HasCRC32 = true // armv8.1
|
||||||
|
ARM64.HasATOMICS = true // armv8.2
|
||||||
|
ARM64.HasJSCVT = true // armv8.3, if HasFP
|
||||||
|
}
|
||||||
|
}
|
||||||
+1
@@ -9,3 +9,4 @@ package cpu
|
|||||||
func getisar0() uint64 { return 0 }
|
func getisar0() uint64 { return 0 }
|
||||||
func getisar1() uint64 { return 0 }
|
func getisar1() uint64 { return 0 }
|
||||||
func getpfr0() uint64 { return 0 }
|
func getpfr0() uint64 { return 0 }
|
||||||
|
func getzfr0() uint64 { return 0 }
|
||||||
|
|||||||
+4
-2
@@ -2,8 +2,10 @@
|
|||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build !linux && !netbsd && !openbsd && !windows && arm64
|
//go:build !darwin && !linux && !netbsd && !openbsd && arm64
|
||||||
|
|
||||||
package cpu
|
package cpu
|
||||||
|
|
||||||
func doinit() {}
|
func doinit() {
|
||||||
|
setMinimalFeatures()
|
||||||
|
}
|
||||||
|
|||||||
-42
@@ -1,42 +0,0 @@
|
|||||||
// Copyright 2026 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package cpu
|
|
||||||
|
|
||||||
import (
|
|
||||||
"golang.org/x/sys/windows"
|
|
||||||
)
|
|
||||||
|
|
||||||
func doinit() {
|
|
||||||
// set HasASIMD and HasFP to true as per
|
|
||||||
// https://learn.microsoft.com/en-us/cpp/build/arm64-windows-abi-conventions?view=msvc-170#base-requirements
|
|
||||||
//
|
|
||||||
// The ARM64 version of Windows always presupposes that it's running on an ARMv8 or later architecture.
|
|
||||||
// Both floating-point and NEON support are presumed to be present in hardware.
|
|
||||||
//
|
|
||||||
ARM64.HasASIMD = true
|
|
||||||
ARM64.HasFP = true
|
|
||||||
|
|
||||||
if windows.IsProcessorFeaturePresent(windows.PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE) {
|
|
||||||
ARM64.HasAES = true
|
|
||||||
ARM64.HasPMULL = true
|
|
||||||
ARM64.HasSHA1 = true
|
|
||||||
ARM64.HasSHA2 = true
|
|
||||||
}
|
|
||||||
ARM64.HasSHA3 = windows.IsProcessorFeaturePresent(windows.PF_ARM_SHA3_INSTRUCTIONS_AVAILABLE)
|
|
||||||
ARM64.HasCRC32 = windows.IsProcessorFeaturePresent(windows.PF_ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE)
|
|
||||||
ARM64.HasSHA512 = windows.IsProcessorFeaturePresent(windows.PF_ARM_SHA512_INSTRUCTIONS_AVAILABLE)
|
|
||||||
ARM64.HasATOMICS = windows.IsProcessorFeaturePresent(windows.PF_ARM_V81_ATOMIC_INSTRUCTIONS_AVAILABLE)
|
|
||||||
if windows.IsProcessorFeaturePresent(windows.PF_ARM_V82_DP_INSTRUCTIONS_AVAILABLE) {
|
|
||||||
ARM64.HasASIMDDP = true
|
|
||||||
ARM64.HasASIMDRDM = true
|
|
||||||
}
|
|
||||||
if windows.IsProcessorFeaturePresent(windows.PF_ARM_V83_LRCPC_INSTRUCTIONS_AVAILABLE) {
|
|
||||||
ARM64.HasLRCPC = true
|
|
||||||
ARM64.HasSM3 = true
|
|
||||||
}
|
|
||||||
ARM64.HasSVE = windows.IsProcessorFeaturePresent(windows.PF_ARM_SVE_INSTRUCTIONS_AVAILABLE)
|
|
||||||
ARM64.HasSVE2 = windows.IsProcessorFeaturePresent(windows.PF_ARM_SVE2_INSTRUCTIONS_AVAILABLE)
|
|
||||||
ARM64.HasJSCVT = windows.IsProcessorFeaturePresent(windows.PF_ARM_V83_JSCVT_INSTRUCTIONS_AVAILABLE)
|
|
||||||
}
|
|
||||||
+54
@@ -0,0 +1,54 @@
|
|||||||
|
// Copyright 2024 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Minimal copy from internal/cpu and runtime to make sysctl calls.
|
||||||
|
|
||||||
|
//go:build darwin && arm64 && gc
|
||||||
|
|
||||||
|
package cpu
|
||||||
|
|
||||||
|
import (
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Errno = syscall.Errno
|
||||||
|
|
||||||
|
// adapted from internal/cpu/cpu_arm64_darwin.go
|
||||||
|
func darwinSysctlEnabled(name []byte) bool {
|
||||||
|
out := int32(0)
|
||||||
|
nout := unsafe.Sizeof(out)
|
||||||
|
if ret := sysctlbyname(&name[0], (*byte)(unsafe.Pointer(&out)), &nout, nil, 0); ret != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return out > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:cgo_import_dynamic libc_sysctl sysctl "/usr/lib/libSystem.B.dylib"
|
||||||
|
|
||||||
|
var libc_sysctlbyname_trampoline_addr uintptr
|
||||||
|
|
||||||
|
// adapted from runtime/sys_darwin.go in the pattern of sysctl() above, as defined in x/sys/unix
|
||||||
|
func sysctlbyname(name *byte, old *byte, oldlen *uintptr, new *byte, newlen uintptr) error {
|
||||||
|
if _, _, err := syscall_syscall6(
|
||||||
|
libc_sysctlbyname_trampoline_addr,
|
||||||
|
uintptr(unsafe.Pointer(name)),
|
||||||
|
uintptr(unsafe.Pointer(old)),
|
||||||
|
uintptr(unsafe.Pointer(oldlen)),
|
||||||
|
uintptr(unsafe.Pointer(new)),
|
||||||
|
uintptr(newlen),
|
||||||
|
0,
|
||||||
|
); err != 0 {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:cgo_import_dynamic libc_sysctlbyname sysctlbyname "/usr/lib/libSystem.B.dylib"
|
||||||
|
|
||||||
|
// Implemented in the runtime package (runtime/sys_darwin.go)
|
||||||
|
func syscall_syscall6(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno)
|
||||||
|
|
||||||
|
//go:linkname syscall_syscall6 syscall.syscall6
|
||||||
+125
-104
@@ -593,110 +593,115 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
NDA_UNSPEC = 0x0
|
NDA_UNSPEC = 0x0
|
||||||
NDA_DST = 0x1
|
NDA_DST = 0x1
|
||||||
NDA_LLADDR = 0x2
|
NDA_LLADDR = 0x2
|
||||||
NDA_CACHEINFO = 0x3
|
NDA_CACHEINFO = 0x3
|
||||||
NDA_PROBES = 0x4
|
NDA_PROBES = 0x4
|
||||||
NDA_VLAN = 0x5
|
NDA_VLAN = 0x5
|
||||||
NDA_PORT = 0x6
|
NDA_PORT = 0x6
|
||||||
NDA_VNI = 0x7
|
NDA_VNI = 0x7
|
||||||
NDA_IFINDEX = 0x8
|
NDA_IFINDEX = 0x8
|
||||||
NDA_MASTER = 0x9
|
NDA_MASTER = 0x9
|
||||||
NDA_LINK_NETNSID = 0xa
|
NDA_LINK_NETNSID = 0xa
|
||||||
NDA_SRC_VNI = 0xb
|
NDA_SRC_VNI = 0xb
|
||||||
NTF_USE = 0x1
|
NTF_USE = 0x1
|
||||||
NTF_SELF = 0x2
|
NTF_SELF = 0x2
|
||||||
NTF_MASTER = 0x4
|
NTF_MASTER = 0x4
|
||||||
NTF_PROXY = 0x8
|
NTF_PROXY = 0x8
|
||||||
NTF_EXT_LEARNED = 0x10
|
NTF_EXT_LEARNED = 0x10
|
||||||
NTF_OFFLOADED = 0x20
|
NTF_OFFLOADED = 0x20
|
||||||
NTF_ROUTER = 0x80
|
NTF_ROUTER = 0x80
|
||||||
NUD_INCOMPLETE = 0x1
|
NUD_INCOMPLETE = 0x1
|
||||||
NUD_REACHABLE = 0x2
|
NUD_REACHABLE = 0x2
|
||||||
NUD_STALE = 0x4
|
NUD_STALE = 0x4
|
||||||
NUD_DELAY = 0x8
|
NUD_DELAY = 0x8
|
||||||
NUD_PROBE = 0x10
|
NUD_PROBE = 0x10
|
||||||
NUD_FAILED = 0x20
|
NUD_FAILED = 0x20
|
||||||
NUD_NOARP = 0x40
|
NUD_NOARP = 0x40
|
||||||
NUD_PERMANENT = 0x80
|
NUD_PERMANENT = 0x80
|
||||||
NUD_NONE = 0x0
|
NUD_NONE = 0x0
|
||||||
IFA_UNSPEC = 0x0
|
IFA_UNSPEC = 0x0
|
||||||
IFA_ADDRESS = 0x1
|
IFA_ADDRESS = 0x1
|
||||||
IFA_LOCAL = 0x2
|
IFA_LOCAL = 0x2
|
||||||
IFA_LABEL = 0x3
|
IFA_LABEL = 0x3
|
||||||
IFA_BROADCAST = 0x4
|
IFA_BROADCAST = 0x4
|
||||||
IFA_ANYCAST = 0x5
|
IFA_ANYCAST = 0x5
|
||||||
IFA_CACHEINFO = 0x6
|
IFA_CACHEINFO = 0x6
|
||||||
IFA_MULTICAST = 0x7
|
IFA_MULTICAST = 0x7
|
||||||
IFA_FLAGS = 0x8
|
IFA_FLAGS = 0x8
|
||||||
IFA_RT_PRIORITY = 0x9
|
IFA_RT_PRIORITY = 0x9
|
||||||
IFA_TARGET_NETNSID = 0xa
|
IFA_TARGET_NETNSID = 0xa
|
||||||
IFAL_LABEL = 0x2
|
IFAL_LABEL = 0x2
|
||||||
IFAL_ADDRESS = 0x1
|
IFAL_ADDRESS = 0x1
|
||||||
RT_SCOPE_UNIVERSE = 0x0
|
RT_SCOPE_UNIVERSE = 0x0
|
||||||
RT_SCOPE_SITE = 0xc8
|
RT_SCOPE_SITE = 0xc8
|
||||||
RT_SCOPE_LINK = 0xfd
|
RT_SCOPE_LINK = 0xfd
|
||||||
RT_SCOPE_HOST = 0xfe
|
RT_SCOPE_HOST = 0xfe
|
||||||
RT_SCOPE_NOWHERE = 0xff
|
RT_SCOPE_NOWHERE = 0xff
|
||||||
RT_TABLE_UNSPEC = 0x0
|
RT_TABLE_UNSPEC = 0x0
|
||||||
RT_TABLE_COMPAT = 0xfc
|
RT_TABLE_COMPAT = 0xfc
|
||||||
RT_TABLE_DEFAULT = 0xfd
|
RT_TABLE_DEFAULT = 0xfd
|
||||||
RT_TABLE_MAIN = 0xfe
|
RT_TABLE_MAIN = 0xfe
|
||||||
RT_TABLE_LOCAL = 0xff
|
RT_TABLE_LOCAL = 0xff
|
||||||
RT_TABLE_MAX = 0xffffffff
|
RT_TABLE_MAX = 0xffffffff
|
||||||
RTA_UNSPEC = 0x0
|
RTA_UNSPEC = 0x0
|
||||||
RTA_DST = 0x1
|
RTA_DST = 0x1
|
||||||
RTA_SRC = 0x2
|
RTA_SRC = 0x2
|
||||||
RTA_IIF = 0x3
|
RTA_IIF = 0x3
|
||||||
RTA_OIF = 0x4
|
RTA_OIF = 0x4
|
||||||
RTA_GATEWAY = 0x5
|
RTA_GATEWAY = 0x5
|
||||||
RTA_PRIORITY = 0x6
|
RTA_PRIORITY = 0x6
|
||||||
RTA_PREFSRC = 0x7
|
RTA_PREFSRC = 0x7
|
||||||
RTA_METRICS = 0x8
|
RTA_METRICS = 0x8
|
||||||
RTA_MULTIPATH = 0x9
|
RTA_MULTIPATH = 0x9
|
||||||
RTA_FLOW = 0xb
|
RTA_FLOW = 0xb
|
||||||
RTA_CACHEINFO = 0xc
|
RTA_CACHEINFO = 0xc
|
||||||
RTA_TABLE = 0xf
|
RTA_TABLE = 0xf
|
||||||
RTA_MARK = 0x10
|
RTA_MARK = 0x10
|
||||||
RTA_MFC_STATS = 0x11
|
RTA_MFC_STATS = 0x11
|
||||||
RTA_VIA = 0x12
|
RTA_VIA = 0x12
|
||||||
RTA_NEWDST = 0x13
|
RTA_NEWDST = 0x13
|
||||||
RTA_PREF = 0x14
|
RTA_PREF = 0x14
|
||||||
RTA_ENCAP_TYPE = 0x15
|
RTA_ENCAP_TYPE = 0x15
|
||||||
RTA_ENCAP = 0x16
|
RTA_ENCAP = 0x16
|
||||||
RTA_EXPIRES = 0x17
|
RTA_EXPIRES = 0x17
|
||||||
RTA_PAD = 0x18
|
RTA_PAD = 0x18
|
||||||
RTA_UID = 0x19
|
RTA_UID = 0x19
|
||||||
RTA_TTL_PROPAGATE = 0x1a
|
RTA_TTL_PROPAGATE = 0x1a
|
||||||
RTA_IP_PROTO = 0x1b
|
RTA_IP_PROTO = 0x1b
|
||||||
RTA_SPORT = 0x1c
|
RTA_SPORT = 0x1c
|
||||||
RTA_DPORT = 0x1d
|
RTA_DPORT = 0x1d
|
||||||
RTN_UNSPEC = 0x0
|
RTN_UNSPEC = 0x0
|
||||||
RTN_UNICAST = 0x1
|
RTN_UNICAST = 0x1
|
||||||
RTN_LOCAL = 0x2
|
RTN_LOCAL = 0x2
|
||||||
RTN_BROADCAST = 0x3
|
RTN_BROADCAST = 0x3
|
||||||
RTN_ANYCAST = 0x4
|
RTN_ANYCAST = 0x4
|
||||||
RTN_MULTICAST = 0x5
|
RTN_MULTICAST = 0x5
|
||||||
RTN_BLACKHOLE = 0x6
|
RTN_BLACKHOLE = 0x6
|
||||||
RTN_UNREACHABLE = 0x7
|
RTN_UNREACHABLE = 0x7
|
||||||
RTN_PROHIBIT = 0x8
|
RTN_PROHIBIT = 0x8
|
||||||
RTN_THROW = 0x9
|
RTN_THROW = 0x9
|
||||||
RTN_NAT = 0xa
|
RTN_NAT = 0xa
|
||||||
RTN_XRESOLVE = 0xb
|
RTN_XRESOLVE = 0xb
|
||||||
SizeofNlMsghdr = 0x10
|
PREFIX_UNSPEC = 0x0
|
||||||
SizeofNlMsgerr = 0x14
|
PREFIX_ADDRESS = 0x1
|
||||||
SizeofRtGenmsg = 0x1
|
PREFIX_CACHEINFO = 0x2
|
||||||
SizeofNlAttr = 0x4
|
SizeofNlMsghdr = 0x10
|
||||||
SizeofRtAttr = 0x4
|
SizeofNlMsgerr = 0x14
|
||||||
SizeofIfInfomsg = 0x10
|
SizeofRtGenmsg = 0x1
|
||||||
SizeofIfAddrmsg = 0x8
|
SizeofNlAttr = 0x4
|
||||||
SizeofIfAddrlblmsg = 0xc
|
SizeofRtAttr = 0x4
|
||||||
SizeofIfaCacheinfo = 0x10
|
SizeofIfInfomsg = 0x10
|
||||||
SizeofRtMsg = 0xc
|
SizeofPrefixmsg = 0xc
|
||||||
SizeofRtNexthop = 0x8
|
SizeofPrefixCacheinfo = 0x8
|
||||||
SizeofNdUseroptmsg = 0x10
|
SizeofIfAddrmsg = 0x8
|
||||||
SizeofNdMsg = 0xc
|
SizeofIfAddrlblmsg = 0xc
|
||||||
|
SizeofIfaCacheinfo = 0x10
|
||||||
|
SizeofRtMsg = 0xc
|
||||||
|
SizeofRtNexthop = 0x8
|
||||||
|
SizeofNdUseroptmsg = 0x10
|
||||||
|
SizeofNdMsg = 0xc
|
||||||
)
|
)
|
||||||
|
|
||||||
type NlMsghdr struct {
|
type NlMsghdr struct {
|
||||||
@@ -735,6 +740,22 @@ type IfInfomsg struct {
|
|||||||
Change uint32
|
Change uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Prefixmsg struct {
|
||||||
|
Family uint8
|
||||||
|
Pad1 uint8
|
||||||
|
Pad2 uint16
|
||||||
|
Ifindex int32
|
||||||
|
Type uint8
|
||||||
|
Len uint8
|
||||||
|
Flags uint8
|
||||||
|
Pad3 uint8
|
||||||
|
}
|
||||||
|
|
||||||
|
type PrefixCacheinfo struct {
|
||||||
|
Preferred_time uint32
|
||||||
|
Valid_time uint32
|
||||||
|
}
|
||||||
|
|
||||||
type IfAddrmsg struct {
|
type IfAddrmsg struct {
|
||||||
Family uint8
|
Family uint8
|
||||||
Prefixlen uint8
|
Prefixlen uint8
|
||||||
|
|||||||
+1
@@ -8,5 +8,6 @@ package windows
|
|||||||
|
|
||||||
import "syscall"
|
import "syscall"
|
||||||
|
|
||||||
|
type Signal = syscall.Signal
|
||||||
type Errno = syscall.Errno
|
type Errno = syscall.Errno
|
||||||
type SysProcAttr = syscall.SysProcAttr
|
type SysProcAttr = syscall.SysProcAttr
|
||||||
|
|||||||
+1
-36
@@ -163,42 +163,7 @@ func (p *Proc) Addr() uintptr {
|
|||||||
// (according to the semantics of the specific function being called) before consulting
|
// (according to the semantics of the specific function being called) before consulting
|
||||||
// the error. The error will be guaranteed to contain windows.Errno.
|
// the error. The error will be guaranteed to contain windows.Errno.
|
||||||
func (p *Proc) Call(a ...uintptr) (r1, r2 uintptr, lastErr error) {
|
func (p *Proc) Call(a ...uintptr) (r1, r2 uintptr, lastErr error) {
|
||||||
switch len(a) {
|
return syscall.SyscallN(p.Addr(), a...)
|
||||||
case 0:
|
|
||||||
return syscall.Syscall(p.Addr(), uintptr(len(a)), 0, 0, 0)
|
|
||||||
case 1:
|
|
||||||
return syscall.Syscall(p.Addr(), uintptr(len(a)), a[0], 0, 0)
|
|
||||||
case 2:
|
|
||||||
return syscall.Syscall(p.Addr(), uintptr(len(a)), a[0], a[1], 0)
|
|
||||||
case 3:
|
|
||||||
return syscall.Syscall(p.Addr(), uintptr(len(a)), a[0], a[1], a[2])
|
|
||||||
case 4:
|
|
||||||
return syscall.Syscall6(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], 0, 0)
|
|
||||||
case 5:
|
|
||||||
return syscall.Syscall6(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], 0)
|
|
||||||
case 6:
|
|
||||||
return syscall.Syscall6(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], a[5])
|
|
||||||
case 7:
|
|
||||||
return syscall.Syscall9(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], a[5], a[6], 0, 0)
|
|
||||||
case 8:
|
|
||||||
return syscall.Syscall9(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], 0)
|
|
||||||
case 9:
|
|
||||||
return syscall.Syscall9(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8])
|
|
||||||
case 10:
|
|
||||||
return syscall.Syscall12(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], 0, 0)
|
|
||||||
case 11:
|
|
||||||
return syscall.Syscall12(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], 0)
|
|
||||||
case 12:
|
|
||||||
return syscall.Syscall12(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11])
|
|
||||||
case 13:
|
|
||||||
return syscall.Syscall15(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], 0, 0)
|
|
||||||
case 14:
|
|
||||||
return syscall.Syscall15(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], 0)
|
|
||||||
case 15:
|
|
||||||
return syscall.Syscall15(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], a[14])
|
|
||||||
default:
|
|
||||||
panic("Call " + p.Name + " with too many arguments " + itoa(len(a)) + ".")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// A LazyDLL implements access to a single DLL.
|
// A LazyDLL implements access to a single DLL.
|
||||||
|
|||||||
+5
-1
@@ -1438,13 +1438,17 @@ func GetSecurityInfo(handle Handle, objectType SE_OBJECT_TYPE, securityInformati
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetNamedSecurityInfo queries the security information for a given named object and returns the self-relative security
|
// GetNamedSecurityInfo queries the security information for a given named object and returns the self-relative security
|
||||||
// descriptor result on the Go heap.
|
// descriptor result on the Go heap. The security descriptor might be nil, even when err is nil, if the object exists
|
||||||
|
// but has no security descriptor.
|
||||||
func GetNamedSecurityInfo(objectName string, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION) (sd *SECURITY_DESCRIPTOR, err error) {
|
func GetNamedSecurityInfo(objectName string, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION) (sd *SECURITY_DESCRIPTOR, err error) {
|
||||||
var winHeapSD *SECURITY_DESCRIPTOR
|
var winHeapSD *SECURITY_DESCRIPTOR
|
||||||
err = getNamedSecurityInfo(objectName, objectType, securityInformation, nil, nil, nil, nil, &winHeapSD)
|
err = getNamedSecurityInfo(objectName, objectType, securityInformation, nil, nil, nil, nil, &winHeapSD)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if winHeapSD == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
defer LocalFree(Handle(unsafe.Pointer(winHeapSD)))
|
defer LocalFree(Handle(unsafe.Pointer(winHeapSD)))
|
||||||
return winHeapSD.copySelfRelativeSecurityDescriptor(), nil
|
return winHeapSD.copySelfRelativeSecurityDescriptor(), nil
|
||||||
}
|
}
|
||||||
|
|||||||
-14
@@ -1490,20 +1490,6 @@ func Getgid() (gid int) { return -1 }
|
|||||||
func Getegid() (egid int) { return -1 }
|
func Getegid() (egid int) { return -1 }
|
||||||
func Getgroups() (gids []int, err error) { return nil, syscall.EWINDOWS }
|
func Getgroups() (gids []int, err error) { return nil, syscall.EWINDOWS }
|
||||||
|
|
||||||
type Signal int
|
|
||||||
|
|
||||||
func (s Signal) Signal() {}
|
|
||||||
|
|
||||||
func (s Signal) String() string {
|
|
||||||
if 0 <= s && int(s) < len(signals) {
|
|
||||||
str := signals[s]
|
|
||||||
if str != "" {
|
|
||||||
return str
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return "signal " + itoa(int(s))
|
|
||||||
}
|
|
||||||
|
|
||||||
func LoadCreateSymbolicLink() error {
|
func LoadCreateSymbolicLink() error {
|
||||||
return procCreateSymbolicLinkW.Find()
|
return procCreateSymbolicLinkW.Find()
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+8
-8
@@ -80,8 +80,8 @@ github.com/go-git/gcfg
|
|||||||
github.com/go-git/gcfg/scanner
|
github.com/go-git/gcfg/scanner
|
||||||
github.com/go-git/gcfg/token
|
github.com/go-git/gcfg/token
|
||||||
github.com/go-git/gcfg/types
|
github.com/go-git/gcfg/types
|
||||||
# github.com/go-git/go-billy/v5 v5.7.0
|
# github.com/go-git/go-billy/v5 v5.9.0
|
||||||
## explicit; go 1.23.0
|
## explicit; go 1.25.0
|
||||||
github.com/go-git/go-billy/v5
|
github.com/go-git/go-billy/v5
|
||||||
github.com/go-git/go-billy/v5/helper/chroot
|
github.com/go-git/go-billy/v5/helper/chroot
|
||||||
github.com/go-git/go-billy/v5/helper/polyfill
|
github.com/go-git/go-billy/v5/helper/polyfill
|
||||||
@@ -177,8 +177,8 @@ github.com/spf13/pflag
|
|||||||
# github.com/xanzy/ssh-agent v0.3.3
|
# github.com/xanzy/ssh-agent v0.3.3
|
||||||
## explicit; go 1.16
|
## explicit; go 1.16
|
||||||
github.com/xanzy/ssh-agent
|
github.com/xanzy/ssh-agent
|
||||||
# golang.org/x/crypto v0.48.0
|
# golang.org/x/crypto v0.50.0
|
||||||
## explicit; go 1.24.0
|
## explicit; go 1.25.0
|
||||||
golang.org/x/crypto/argon2
|
golang.org/x/crypto/argon2
|
||||||
golang.org/x/crypto/blake2b
|
golang.org/x/crypto/blake2b
|
||||||
golang.org/x/crypto/blowfish
|
golang.org/x/crypto/blowfish
|
||||||
@@ -195,13 +195,13 @@ golang.org/x/crypto/ssh
|
|||||||
golang.org/x/crypto/ssh/agent
|
golang.org/x/crypto/ssh/agent
|
||||||
golang.org/x/crypto/ssh/internal/bcrypt_pbkdf
|
golang.org/x/crypto/ssh/internal/bcrypt_pbkdf
|
||||||
golang.org/x/crypto/ssh/knownhosts
|
golang.org/x/crypto/ssh/knownhosts
|
||||||
# golang.org/x/net v0.50.0
|
# golang.org/x/net v0.53.0
|
||||||
## explicit; go 1.24.0
|
## explicit; go 1.25.0
|
||||||
golang.org/x/net/context
|
golang.org/x/net/context
|
||||||
golang.org/x/net/internal/socks
|
golang.org/x/net/internal/socks
|
||||||
golang.org/x/net/proxy
|
golang.org/x/net/proxy
|
||||||
# golang.org/x/sys v0.41.0
|
# golang.org/x/sys v0.43.0
|
||||||
## explicit; go 1.24.0
|
## explicit; go 1.25.0
|
||||||
golang.org/x/sys/cpu
|
golang.org/x/sys/cpu
|
||||||
golang.org/x/sys/execabs
|
golang.org/x/sys/execabs
|
||||||
golang.org/x/sys/unix
|
golang.org/x/sys/unix
|
||||||
|
|||||||
Reference in New Issue
Block a user