mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-10-31 18:28:13 +00:00 
			
		
		
		
	updating microsft/go-winio package to latest version
Signed-off-by: Mark Rossetti <marosset@microsoft.com>
This commit is contained in:
		
							
								
								
									
										2
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								go.mod
									
									
									
									
									
								
							| @@ -15,7 +15,7 @@ require ( | ||||
| 	github.com/Azure/go-autorest/autorest/adal v0.9.23 | ||||
| 	github.com/GoogleCloudPlatform/k8s-cloud-provider v1.18.1-0.20220218231025-f11817397a1b | ||||
| 	github.com/JeffAshton/win_pdh v0.0.0-20161109143554-76bb4ee9f0ab | ||||
| 	github.com/Microsoft/go-winio v0.4.17 | ||||
| 	github.com/Microsoft/go-winio v0.6.0 | ||||
| 	github.com/Microsoft/hcsshim v0.8.25 | ||||
| 	github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e | ||||
| 	github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 | ||||
|   | ||||
							
								
								
									
										3
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										3
									
								
								go.sum
									
									
									
									
									
								
							| @@ -82,8 +82,9 @@ github.com/JeffAshton/win_pdh v0.0.0-20161109143554-76bb4ee9f0ab/go.mod h1:3VYc5 | ||||
| github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ= | ||||
| github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE= | ||||
| github.com/Microsoft/go-winio v0.4.15/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw= | ||||
| github.com/Microsoft/go-winio v0.4.17 h1:iT12IBVClFevaf8PuVyi3UmZOVh4OqnaLxDTW2O6j3w= | ||||
| github.com/Microsoft/go-winio v0.4.17/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= | ||||
| github.com/Microsoft/go-winio v0.6.0 h1:slsWYD/zyx7lCXoZVlvQrj0hPTM1HI4+v1sIda2yDvg= | ||||
| github.com/Microsoft/go-winio v0.6.0/go.mod h1:cTAf44im0RAYeL23bpB+fzCyDH2MJiz2BO69KH/soAE= | ||||
| github.com/Microsoft/hcsshim v0.8.25 h1:fRMwXiwk3qDwc0P05eHnh+y2v07JdtsfQ1fuAc69m9g= | ||||
| github.com/Microsoft/hcsshim v0.8.25/go.mod h1:4zegtUJth7lAvFyc6cH2gGQ5B3OFQim01nnU2M8jKDg= | ||||
| github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cqUQ3I= | ||||
|   | ||||
| @@ -83,7 +83,6 @@ | ||||
|         "sigs.k8s.io/structured-merge-diff/v4" | ||||
|       ], | ||||
|       "github.com/pkg/errors": [ | ||||
|         "github.com/Microsoft/go-winio", | ||||
|         "github.com/Microsoft/hcsshim", | ||||
|         "github.com/aws/aws-sdk-go", | ||||
|         "github.com/containerd/cgroups", | ||||
|   | ||||
							
								
								
									
										1
									
								
								vendor/github.com/Microsoft/go-winio/.gitattributes
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								vendor/github.com/Microsoft/go-winio/.gitattributes
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| * text=auto eol=lf | ||||
							
								
								
									
										9
									
								
								vendor/github.com/Microsoft/go-winio/.gitignore
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										9
									
								
								vendor/github.com/Microsoft/go-winio/.gitignore
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1 +1,10 @@ | ||||
| .vscode/ | ||||
|  | ||||
| *.exe | ||||
|  | ||||
| # testing | ||||
| testdata | ||||
|  | ||||
| # go workspaces | ||||
| go.work | ||||
| go.work.sum | ||||
|   | ||||
							
								
								
									
										144
									
								
								vendor/github.com/Microsoft/go-winio/.golangci.yml
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										144
									
								
								vendor/github.com/Microsoft/go-winio/.golangci.yml
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,144 @@ | ||||
| run: | ||||
|   skip-dirs: | ||||
|     - pkg/etw/sample | ||||
|  | ||||
| linters: | ||||
|   enable: | ||||
|     # style | ||||
|     - containedctx # struct contains a context | ||||
|     - dupl # duplicate code | ||||
|     - errname # erorrs are named correctly | ||||
|     - goconst # strings that should be constants | ||||
|     - godot # comments end in a period | ||||
|     - misspell | ||||
|     - nolintlint # "//nolint" directives are properly explained | ||||
|     - revive # golint replacement | ||||
|     - stylecheck # golint replacement, less configurable than revive | ||||
|     - unconvert # unnecessary conversions | ||||
|     - wastedassign | ||||
|  | ||||
|     # bugs, performance, unused, etc ... | ||||
|     - contextcheck # function uses a non-inherited context | ||||
|     - errorlint # errors not wrapped for 1.13 | ||||
|     - exhaustive # check exhaustiveness of enum switch statements | ||||
|     - gofmt # files are gofmt'ed | ||||
|     - gosec # security | ||||
|     - nestif # deeply nested ifs | ||||
|     - nilerr # returns nil even with non-nil error | ||||
|     - prealloc # slices that can be pre-allocated | ||||
|     - structcheck # unused struct fields | ||||
|     - unparam # unused function params | ||||
|  | ||||
| issues: | ||||
|   exclude-rules: | ||||
|     # err is very often shadowed in nested scopes | ||||
|     - linters: | ||||
|         - govet | ||||
|       text: '^shadow: declaration of "err" shadows declaration' | ||||
|  | ||||
|     # ignore long lines for skip autogen directives | ||||
|     - linters: | ||||
|         - revive | ||||
|       text: "^line-length-limit: " | ||||
|       source: "^//(go:generate|sys) " | ||||
|  | ||||
|     # allow unjustified ignores of error checks in defer statements | ||||
|     - linters: | ||||
|         - nolintlint | ||||
|       text: "^directive `//nolint:errcheck` should provide explanation" | ||||
|       source: '^\s*defer ' | ||||
|  | ||||
|     # allow unjustified ignores of error lints for io.EOF | ||||
|     - linters: | ||||
|         - nolintlint | ||||
|       text: "^directive `//nolint:errorlint` should provide explanation" | ||||
|       source: '[=|!]= io.EOF' | ||||
|  | ||||
|  | ||||
| linters-settings: | ||||
|   govet: | ||||
|     enable-all: true | ||||
|     disable: | ||||
|       # struct order is often for Win32 compat | ||||
|       # also, ignore pointer bytes/GC issues for now until performance becomes an issue | ||||
|       - fieldalignment | ||||
|     check-shadowing: true | ||||
|   nolintlint: | ||||
|     allow-leading-space: false | ||||
|     require-explanation: true | ||||
|     require-specific: true | ||||
|   revive: | ||||
|     # revive is more configurable than static check, so likely the preferred alternative to static-check | ||||
|     # (once the perf issue is solved: https://github.com/golangci/golangci-lint/issues/2997) | ||||
|     enable-all-rules: | ||||
|       true | ||||
|       # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md | ||||
|     rules: | ||||
|       # rules with required arguments | ||||
|       - name: argument-limit | ||||
|         disabled: true | ||||
|       - name: banned-characters | ||||
|         disabled: true | ||||
|       - name: cognitive-complexity | ||||
|         disabled: true | ||||
|       - name: cyclomatic | ||||
|         disabled: true | ||||
|       - name: file-header | ||||
|         disabled: true | ||||
|       - name: function-length | ||||
|         disabled: true | ||||
|       - name: function-result-limit | ||||
|         disabled: true | ||||
|       - name: max-public-structs | ||||
|         disabled: true | ||||
|       # geneally annoying rules | ||||
|       - name: add-constant # complains about any and all strings and integers | ||||
|         disabled: true | ||||
|       - name: confusing-naming # we frequently use "Foo()" and "foo()" together | ||||
|         disabled: true | ||||
|       - name: flag-parameter # excessive, and a common idiom we use | ||||
|         disabled: true | ||||
|       # general config | ||||
|       - name: line-length-limit | ||||
|         arguments: | ||||
|           - 140 | ||||
|       - name: var-naming | ||||
|         arguments: | ||||
|           - [] | ||||
|           - - CID | ||||
|             - CRI | ||||
|             - CTRD | ||||
|             - DACL | ||||
|             - DLL | ||||
|             - DOS | ||||
|             - ETW | ||||
|             - FSCTL | ||||
|             - GCS | ||||
|             - GMSA | ||||
|             - HCS | ||||
|             - HV | ||||
|             - IO | ||||
|             - LCOW | ||||
|             - LDAP | ||||
|             - LPAC | ||||
|             - LTSC | ||||
|             - MMIO | ||||
|             - NT | ||||
|             - OCI | ||||
|             - PMEM | ||||
|             - PWSH | ||||
|             - RX | ||||
|             - SACl | ||||
|             - SID | ||||
|             - SMB | ||||
|             - TX | ||||
|             - VHD | ||||
|             - VHDX | ||||
|             - VMID | ||||
|             - VPCI | ||||
|             - WCOW | ||||
|             - WIM | ||||
|   stylecheck: | ||||
|     checks: | ||||
|       - "all" | ||||
|       - "-ST1003" # use revive's var naming | ||||
							
								
								
									
										85
									
								
								vendor/github.com/Microsoft/go-winio/README.md
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										85
									
								
								vendor/github.com/Microsoft/go-winio/README.md
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,4 +1,4 @@ | ||||
| # go-winio | ||||
| # go-winio [](https://github.com/microsoft/go-winio/actions/workflows/ci.yml) | ||||
|  | ||||
| This repository contains utilities for efficiently performing Win32 IO operations in | ||||
| Go. Currently, this is focused on accessing named pipes and other file handles, and | ||||
| @@ -11,12 +11,79 @@ package. | ||||
|  | ||||
| Please see the LICENSE file for licensing information. | ||||
|  | ||||
| This project has adopted the [Microsoft Open Source Code of | ||||
| Conduct](https://opensource.microsoft.com/codeofconduct/). For more information | ||||
| see the [Code of Conduct | ||||
| FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact | ||||
| [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional | ||||
| questions or comments. | ||||
| ## Contributing | ||||
|  | ||||
| Thanks to natefinch for the inspiration for this library. See https://github.com/natefinch/npipe | ||||
| for another named pipe implementation. | ||||
| This project welcomes contributions and suggestions. | ||||
| Most contributions require you to agree to a Contributor License Agreement (CLA) declaring that | ||||
| you have the right to, and actually do, grant us the rights to use your contribution. | ||||
| For details, visit [Microsoft CLA](https://cla.microsoft.com). | ||||
|  | ||||
| When you submit a pull request, a CLA-bot will automatically determine whether you need to | ||||
| provide a CLA and decorate the PR appropriately (e.g., label, comment). | ||||
| Simply follow the instructions provided by the bot. | ||||
| You will only need to do this once across all repos using our CLA. | ||||
|  | ||||
| Additionally, the pull request pipeline requires the following steps to be performed before | ||||
| mergining. | ||||
|  | ||||
| ### Code Sign-Off | ||||
|  | ||||
| We require that contributors sign their commits using [`git commit --signoff`][git-commit-s] | ||||
| to certify they either authored the work themselves or otherwise have permission to use it in this project. | ||||
|  | ||||
| A range of commits can be signed off using [`git rebase --signoff`][git-rebase-s]. | ||||
|  | ||||
| Please see [the developer certificate](https://developercertificate.org) for more info, | ||||
| as well as to make sure that you can attest to the rules listed. | ||||
| Our CI uses the DCO Github app to ensure that all commits in a given PR are signed-off. | ||||
|  | ||||
| ### Linting | ||||
|  | ||||
| Code must pass a linting stage, which uses [`golangci-lint`][lint]. | ||||
| The linting settings are stored in [`.golangci.yaml`](./.golangci.yaml), and can be run | ||||
| automatically with VSCode by adding the following to your workspace or folder settings: | ||||
|  | ||||
| ```json | ||||
|     "go.lintTool": "golangci-lint", | ||||
|     "go.lintOnSave": "package", | ||||
| ``` | ||||
|  | ||||
| Additional editor [integrations options are also available][lint-ide]. | ||||
|  | ||||
| Alternatively, `golangci-lint` can be [installed locally][lint-install] and run from the repo root: | ||||
|  | ||||
| ```shell | ||||
| # use . or specify a path to only lint a package | ||||
| # to show all lint errors, use flags "--max-issues-per-linter=0 --max-same-issues=0" | ||||
| > golangci-lint run ./... | ||||
| ``` | ||||
|  | ||||
| ### Go Generate | ||||
|  | ||||
| The pipeline checks that auto-generated code, via `go generate`, are up to date. | ||||
|  | ||||
| This can be done for the entire repo: | ||||
|  | ||||
| ```shell | ||||
| > go generate ./... | ||||
| ``` | ||||
|  | ||||
| ## Code of Conduct | ||||
|  | ||||
| This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). | ||||
| For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or | ||||
| contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. | ||||
|  | ||||
| ## Special Thanks | ||||
|  | ||||
| Thanks to [natefinch][natefinch] for the inspiration for this library. | ||||
| See [npipe](https://github.com/natefinch/npipe) for another named pipe implementation. | ||||
|  | ||||
| [lint]: https://golangci-lint.run/ | ||||
| [lint-ide]: https://golangci-lint.run/usage/integrations/#editor-integration | ||||
| [lint-install]: https://golangci-lint.run/usage/install/#local-installation | ||||
|  | ||||
| [git-commit-s]: https://git-scm.com/docs/git-commit#Documentation/git-commit.txt--s | ||||
| [git-rebase-s]: https://git-scm.com/docs/git-rebase#Documentation/git-rebase.txt---signoff | ||||
|  | ||||
| [natefinch]: https://github.com/natefinch | ||||
|   | ||||
							
								
								
									
										41
									
								
								vendor/github.com/Microsoft/go-winio/SECURITY.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								vendor/github.com/Microsoft/go-winio/SECURITY.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,41 @@ | ||||
| <!-- BEGIN MICROSOFT SECURITY.MD V0.0.7 BLOCK --> | ||||
|  | ||||
| ## Security | ||||
|  | ||||
| Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/). | ||||
|  | ||||
| If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://aka.ms/opensource/security/definition), please report it to us as described below. | ||||
|  | ||||
| ## Reporting Security Issues | ||||
|  | ||||
| **Please do not report security vulnerabilities through public GitHub issues.** | ||||
|  | ||||
| Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://aka.ms/opensource/security/create-report). | ||||
|  | ||||
| If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com).  If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://aka.ms/opensource/security/pgpkey). | ||||
|  | ||||
| You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://aka.ms/opensource/security/msrc).  | ||||
|  | ||||
| Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue: | ||||
|  | ||||
|   * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.) | ||||
|   * Full paths of source file(s) related to the manifestation of the issue | ||||
|   * The location of the affected source code (tag/branch/commit or direct URL) | ||||
|   * Any special configuration required to reproduce the issue | ||||
|   * Step-by-step instructions to reproduce the issue | ||||
|   * Proof-of-concept or exploit code (if possible) | ||||
|   * Impact of the issue, including how an attacker might exploit the issue | ||||
|  | ||||
| This information will help us triage your report more quickly. | ||||
|  | ||||
| If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://aka.ms/opensource/security/bounty) page for more details about our active programs. | ||||
|  | ||||
| ## Preferred Languages | ||||
|  | ||||
| We prefer all communications to be in English. | ||||
|  | ||||
| ## Policy | ||||
|  | ||||
| Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://aka.ms/opensource/security/cvd). | ||||
|  | ||||
| <!-- END MICROSOFT SECURITY.MD BLOCK --> | ||||
							
								
								
									
										48
									
								
								vendor/github.com/Microsoft/go-winio/backup.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										48
									
								
								vendor/github.com/Microsoft/go-winio/backup.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,3 +1,4 @@ | ||||
| //go:build windows | ||||
| // +build windows | ||||
|  | ||||
| package winio | ||||
| @@ -7,11 +8,12 @@ import ( | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"io" | ||||
| 	"io/ioutil" | ||||
| 	"os" | ||||
| 	"runtime" | ||||
| 	"syscall" | ||||
| 	"unicode/utf16" | ||||
|  | ||||
| 	"golang.org/x/sys/windows" | ||||
| ) | ||||
|  | ||||
| //sys backupRead(h syscall.Handle, b []byte, bytesRead *uint32, abort bool, processSecurity bool, context *uintptr) (err error) = BackupRead | ||||
| @@ -24,7 +26,7 @@ const ( | ||||
| 	BackupAlternateData | ||||
| 	BackupLink | ||||
| 	BackupPropertyData | ||||
| 	BackupObjectId | ||||
| 	BackupObjectId //revive:disable-line:var-naming ID, not Id | ||||
| 	BackupReparseData | ||||
| 	BackupSparseBlock | ||||
| 	BackupTxfsData | ||||
| @@ -34,14 +36,16 @@ const ( | ||||
| 	StreamSparseAttributes = uint32(8) | ||||
| ) | ||||
|  | ||||
| //nolint:revive // var-naming: ALL_CAPS | ||||
| const ( | ||||
| 	WRITE_DAC              = 0x40000 | ||||
| 	WRITE_OWNER            = 0x80000 | ||||
| 	ACCESS_SYSTEM_SECURITY = 0x1000000 | ||||
| 	WRITE_DAC              = windows.WRITE_DAC | ||||
| 	WRITE_OWNER            = windows.WRITE_OWNER | ||||
| 	ACCESS_SYSTEM_SECURITY = windows.ACCESS_SYSTEM_SECURITY | ||||
| ) | ||||
|  | ||||
| // BackupHeader represents a backup stream of a file. | ||||
| type BackupHeader struct { | ||||
| 	//revive:disable-next-line:var-naming ID, not Id | ||||
| 	Id         uint32 // The backup stream ID | ||||
| 	Attributes uint32 // Stream attributes | ||||
| 	Size       int64  // The size of the stream in bytes | ||||
| @@ -49,8 +53,8 @@ type BackupHeader struct { | ||||
| 	Offset     int64  // The offset of the stream in the file (for BackupSparseBlock only). | ||||
| } | ||||
|  | ||||
| type win32StreamId struct { | ||||
| 	StreamId   uint32 | ||||
| type win32StreamID struct { | ||||
| 	StreamID   uint32 | ||||
| 	Attributes uint32 | ||||
| 	Size       uint64 | ||||
| 	NameSize   uint32 | ||||
| @@ -71,7 +75,7 @@ func NewBackupStreamReader(r io.Reader) *BackupStreamReader { | ||||
| // Next returns the next backup stream and prepares for calls to Read(). It skips the remainder of the current stream if | ||||
| // it was not completely read. | ||||
| func (r *BackupStreamReader) Next() (*BackupHeader, error) { | ||||
| 	if r.bytesLeft > 0 { | ||||
| 	if r.bytesLeft > 0 { //nolint:nestif // todo: flatten this | ||||
| 		if s, ok := r.r.(io.Seeker); ok { | ||||
| 			// Make sure Seek on io.SeekCurrent sometimes succeeds | ||||
| 			// before trying the actual seek. | ||||
| @@ -82,16 +86,16 @@ func (r *BackupStreamReader) Next() (*BackupHeader, error) { | ||||
| 				r.bytesLeft = 0 | ||||
| 			} | ||||
| 		} | ||||
| 		if _, err := io.Copy(ioutil.Discard, r); err != nil { | ||||
| 		if _, err := io.Copy(io.Discard, r); err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 	} | ||||
| 	var wsi win32StreamId | ||||
| 	var wsi win32StreamID | ||||
| 	if err := binary.Read(r.r, binary.LittleEndian, &wsi); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	hdr := &BackupHeader{ | ||||
| 		Id:         wsi.StreamId, | ||||
| 		Id:         wsi.StreamID, | ||||
| 		Attributes: wsi.Attributes, | ||||
| 		Size:       int64(wsi.Size), | ||||
| 	} | ||||
| @@ -102,7 +106,7 @@ func (r *BackupStreamReader) Next() (*BackupHeader, error) { | ||||
| 		} | ||||
| 		hdr.Name = syscall.UTF16ToString(name) | ||||
| 	} | ||||
| 	if wsi.StreamId == BackupSparseBlock { | ||||
| 	if wsi.StreamID == BackupSparseBlock { | ||||
| 		if err := binary.Read(r.r, binary.LittleEndian, &hdr.Offset); err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| @@ -147,8 +151,8 @@ func (w *BackupStreamWriter) WriteHeader(hdr *BackupHeader) error { | ||||
| 		return fmt.Errorf("missing %d bytes", w.bytesLeft) | ||||
| 	} | ||||
| 	name := utf16.Encode([]rune(hdr.Name)) | ||||
| 	wsi := win32StreamId{ | ||||
| 		StreamId:   hdr.Id, | ||||
| 	wsi := win32StreamID{ | ||||
| 		StreamID:   hdr.Id, | ||||
| 		Attributes: hdr.Attributes, | ||||
| 		Size:       uint64(hdr.Size), | ||||
| 		NameSize:   uint32(len(name) * 2), | ||||
| @@ -203,7 +207,7 @@ func (r *BackupFileReader) Read(b []byte) (int, error) { | ||||
| 	var bytesRead uint32 | ||||
| 	err := backupRead(syscall.Handle(r.f.Fd()), b, &bytesRead, false, r.includeSecurity, &r.ctx) | ||||
| 	if err != nil { | ||||
| 		return 0, &os.PathError{"BackupRead", r.f.Name(), err} | ||||
| 		return 0, &os.PathError{Op: "BackupRead", Path: r.f.Name(), Err: err} | ||||
| 	} | ||||
| 	runtime.KeepAlive(r.f) | ||||
| 	if bytesRead == 0 { | ||||
| @@ -216,7 +220,7 @@ func (r *BackupFileReader) Read(b []byte) (int, error) { | ||||
| // the underlying file. | ||||
| func (r *BackupFileReader) Close() error { | ||||
| 	if r.ctx != 0 { | ||||
| 		backupRead(syscall.Handle(r.f.Fd()), nil, nil, true, false, &r.ctx) | ||||
| 		_ = backupRead(syscall.Handle(r.f.Fd()), nil, nil, true, false, &r.ctx) | ||||
| 		runtime.KeepAlive(r.f) | ||||
| 		r.ctx = 0 | ||||
| 	} | ||||
| @@ -242,7 +246,7 @@ func (w *BackupFileWriter) Write(b []byte) (int, error) { | ||||
| 	var bytesWritten uint32 | ||||
| 	err := backupWrite(syscall.Handle(w.f.Fd()), b, &bytesWritten, false, w.includeSecurity, &w.ctx) | ||||
| 	if err != nil { | ||||
| 		return 0, &os.PathError{"BackupWrite", w.f.Name(), err} | ||||
| 		return 0, &os.PathError{Op: "BackupWrite", Path: w.f.Name(), Err: err} | ||||
| 	} | ||||
| 	runtime.KeepAlive(w.f) | ||||
| 	if int(bytesWritten) != len(b) { | ||||
| @@ -255,7 +259,7 @@ func (w *BackupFileWriter) Write(b []byte) (int, error) { | ||||
| // close the underlying file. | ||||
| func (w *BackupFileWriter) Close() error { | ||||
| 	if w.ctx != 0 { | ||||
| 		backupWrite(syscall.Handle(w.f.Fd()), nil, nil, true, false, &w.ctx) | ||||
| 		_ = backupWrite(syscall.Handle(w.f.Fd()), nil, nil, true, false, &w.ctx) | ||||
| 		runtime.KeepAlive(w.f) | ||||
| 		w.ctx = 0 | ||||
| 	} | ||||
| @@ -271,7 +275,13 @@ func OpenForBackup(path string, access uint32, share uint32, createmode uint32) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	h, err := syscall.CreateFile(&winPath[0], access, share, nil, createmode, syscall.FILE_FLAG_BACKUP_SEMANTICS|syscall.FILE_FLAG_OPEN_REPARSE_POINT, 0) | ||||
| 	h, err := syscall.CreateFile(&winPath[0], | ||||
| 		access, | ||||
| 		share, | ||||
| 		nil, | ||||
| 		createmode, | ||||
| 		syscall.FILE_FLAG_BACKUP_SEMANTICS|syscall.FILE_FLAG_OPEN_REPARSE_POINT, | ||||
| 		0) | ||||
| 	if err != nil { | ||||
| 		err = &os.PathError{Op: "open", Path: path, Err: err} | ||||
| 		return nil, err | ||||
|   | ||||
							
								
								
									
										22
									
								
								vendor/github.com/Microsoft/go-winio/doc.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								vendor/github.com/Microsoft/go-winio/doc.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,22 @@ | ||||
| // This package provides utilities for efficiently performing Win32 IO operations in Go. | ||||
| // Currently, this package is provides support for genreal IO and management of | ||||
| //   - named pipes | ||||
| //   - files | ||||
| //   - [Hyper-V sockets] | ||||
| // | ||||
| // This code is similar to Go's [net] package, and uses IO completion ports to avoid | ||||
| // blocking IO on system threads, allowing Go to reuse the thread to schedule other goroutines. | ||||
| // | ||||
| // This limits support to Windows Vista and newer operating systems. | ||||
| // | ||||
| // Additionally, this package provides support for: | ||||
| //   - creating and managing GUIDs | ||||
| //   - writing to [ETW] | ||||
| //   - opening and manageing VHDs | ||||
| //   - parsing [Windows Image files] | ||||
| //   - auto-generating Win32 API code | ||||
| // | ||||
| // [Hyper-V sockets]: https://docs.microsoft.com/en-us/virtualization/hyper-v-on-windows/user-guide/make-integration-service | ||||
| // [ETW]: https://docs.microsoft.com/en-us/windows-hardware/drivers/devtest/event-tracing-for-windows--etw- | ||||
| // [Windows Image files]: https://docs.microsoft.com/en-us/windows-hardware/manufacture/desktop/work-with-windows-images | ||||
| package winio | ||||
							
								
								
									
										8
									
								
								vendor/github.com/Microsoft/go-winio/ea.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										8
									
								
								vendor/github.com/Microsoft/go-winio/ea.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -33,7 +33,7 @@ func parseEa(b []byte) (ea ExtendedAttribute, nb []byte, err error) { | ||||
| 	err = binary.Read(bytes.NewReader(b), binary.LittleEndian, &info) | ||||
| 	if err != nil { | ||||
| 		err = errInvalidEaBuffer | ||||
| 		return | ||||
| 		return ea, nb, err | ||||
| 	} | ||||
|  | ||||
| 	nameOffset := fileFullEaInformationSize | ||||
| @@ -43,7 +43,7 @@ func parseEa(b []byte) (ea ExtendedAttribute, nb []byte, err error) { | ||||
| 	nextOffset := int(info.NextEntryOffset) | ||||
| 	if valueLen+valueOffset > len(b) || nextOffset < 0 || nextOffset > len(b) { | ||||
| 		err = errInvalidEaBuffer | ||||
| 		return | ||||
| 		return ea, nb, err | ||||
| 	} | ||||
|  | ||||
| 	ea.Name = string(b[nameOffset : nameOffset+nameLen]) | ||||
| @@ -52,7 +52,7 @@ func parseEa(b []byte) (ea ExtendedAttribute, nb []byte, err error) { | ||||
| 	if info.NextEntryOffset != 0 { | ||||
| 		nb = b[info.NextEntryOffset:] | ||||
| 	} | ||||
| 	return | ||||
| 	return ea, nb, err | ||||
| } | ||||
|  | ||||
| // DecodeExtendedAttributes decodes a list of EAs from a FILE_FULL_EA_INFORMATION | ||||
| @@ -67,7 +67,7 @@ func DecodeExtendedAttributes(b []byte) (eas []ExtendedAttribute, err error) { | ||||
| 		eas = append(eas, ea) | ||||
| 		b = nb | ||||
| 	} | ||||
| 	return | ||||
| 	return eas, err | ||||
| } | ||||
|  | ||||
| func writeEa(buf *bytes.Buffer, ea *ExtendedAttribute, last bool) error { | ||||
|   | ||||
							
								
								
									
										70
									
								
								vendor/github.com/Microsoft/go-winio/file.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										70
									
								
								vendor/github.com/Microsoft/go-winio/file.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,3 +1,4 @@ | ||||
| //go:build windows | ||||
| // +build windows | ||||
|  | ||||
| package winio | ||||
| @@ -10,6 +11,8 @@ import ( | ||||
| 	"sync/atomic" | ||||
| 	"syscall" | ||||
| 	"time" | ||||
|  | ||||
| 	"golang.org/x/sys/windows" | ||||
| ) | ||||
|  | ||||
| //sys cancelIoEx(file syscall.Handle, o *syscall.Overlapped) (err error) = CancelIoEx | ||||
| @@ -23,6 +26,8 @@ type atomicBool int32 | ||||
| func (b *atomicBool) isSet() bool { return atomic.LoadInt32((*int32)(b)) != 0 } | ||||
| func (b *atomicBool) setFalse()   { atomic.StoreInt32((*int32)(b), 0) } | ||||
| func (b *atomicBool) setTrue()    { atomic.StoreInt32((*int32)(b), 1) } | ||||
|  | ||||
| //revive:disable-next-line:predeclared Keep "new" to maintain consistency with "atomic" pkg | ||||
| func (b *atomicBool) swap(new bool) bool { | ||||
| 	var newInt int32 | ||||
| 	if new { | ||||
| @@ -31,11 +36,6 @@ func (b *atomicBool) swap(new bool) bool { | ||||
| 	return atomic.SwapInt32((*int32)(b), newInt) == 1 | ||||
| } | ||||
|  | ||||
| const ( | ||||
| 	cFILE_SKIP_COMPLETION_PORT_ON_SUCCESS = 1 | ||||
| 	cFILE_SKIP_SET_EVENT_ON_HANDLE        = 2 | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| 	ErrFileClosed = errors.New("file has already been closed") | ||||
| 	ErrTimeout    = &timeoutError{} | ||||
| @@ -43,28 +43,28 @@ var ( | ||||
|  | ||||
| type timeoutError struct{} | ||||
|  | ||||
| func (e *timeoutError) Error() string   { return "i/o timeout" } | ||||
| func (e *timeoutError) Timeout() bool   { return true } | ||||
| func (e *timeoutError) Temporary() bool { return true } | ||||
| func (*timeoutError) Error() string   { return "i/o timeout" } | ||||
| func (*timeoutError) Timeout() bool   { return true } | ||||
| func (*timeoutError) Temporary() bool { return true } | ||||
|  | ||||
| type timeoutChan chan struct{} | ||||
|  | ||||
| var ioInitOnce sync.Once | ||||
| var ioCompletionPort syscall.Handle | ||||
|  | ||||
| // ioResult contains the result of an asynchronous IO operation | ||||
| // ioResult contains the result of an asynchronous IO operation. | ||||
| type ioResult struct { | ||||
| 	bytes uint32 | ||||
| 	err   error | ||||
| } | ||||
|  | ||||
| // ioOperation represents an outstanding asynchronous Win32 IO | ||||
| // ioOperation represents an outstanding asynchronous Win32 IO. | ||||
| type ioOperation struct { | ||||
| 	o  syscall.Overlapped | ||||
| 	ch chan ioResult | ||||
| } | ||||
|  | ||||
| func initIo() { | ||||
| func initIO() { | ||||
| 	h, err := createIoCompletionPort(syscall.InvalidHandle, 0, 0, 0xffffffff) | ||||
| 	if err != nil { | ||||
| 		panic(err) | ||||
| @@ -93,15 +93,15 @@ type deadlineHandler struct { | ||||
| 	timedout    atomicBool | ||||
| } | ||||
|  | ||||
| // makeWin32File makes a new win32File from an existing file handle | ||||
| // makeWin32File makes a new win32File from an existing file handle. | ||||
| func makeWin32File(h syscall.Handle) (*win32File, error) { | ||||
| 	f := &win32File{handle: h} | ||||
| 	ioInitOnce.Do(initIo) | ||||
| 	ioInitOnce.Do(initIO) | ||||
| 	_, err := createIoCompletionPort(h, ioCompletionPort, 0, 0xffffffff) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	err = setFileCompletionNotificationModes(h, cFILE_SKIP_COMPLETION_PORT_ON_SUCCESS|cFILE_SKIP_SET_EVENT_ON_HANDLE) | ||||
| 	err = setFileCompletionNotificationModes(h, windows.FILE_SKIP_COMPLETION_PORT_ON_SUCCESS|windows.FILE_SKIP_SET_EVENT_ON_HANDLE) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| @@ -120,14 +120,14 @@ func MakeOpenFile(h syscall.Handle) (io.ReadWriteCloser, error) { | ||||
| 	return f, nil | ||||
| } | ||||
|  | ||||
| // closeHandle closes the resources associated with a Win32 handle | ||||
| // closeHandle closes the resources associated with a Win32 handle. | ||||
| func (f *win32File) closeHandle() { | ||||
| 	f.wgLock.Lock() | ||||
| 	// Atomically set that we are closing, releasing the resources only once. | ||||
| 	if !f.closing.swap(true) { | ||||
| 		f.wgLock.Unlock() | ||||
| 		// cancel all IO and wait for it to complete | ||||
| 		cancelIoEx(f.handle, nil) | ||||
| 		_ = cancelIoEx(f.handle, nil) | ||||
| 		f.wg.Wait() | ||||
| 		// at this point, no new IO can start | ||||
| 		syscall.Close(f.handle) | ||||
| @@ -143,9 +143,14 @@ func (f *win32File) Close() error { | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // prepareIo prepares for a new IO operation. | ||||
| // IsClosed checks if the file has been closed. | ||||
| func (f *win32File) IsClosed() bool { | ||||
| 	return f.closing.isSet() | ||||
| } | ||||
|  | ||||
| // prepareIO prepares for a new IO operation. | ||||
| // The caller must call f.wg.Done() when the IO is finished, prior to Close() returning. | ||||
| func (f *win32File) prepareIo() (*ioOperation, error) { | ||||
| func (f *win32File) prepareIO() (*ioOperation, error) { | ||||
| 	f.wgLock.RLock() | ||||
| 	if f.closing.isSet() { | ||||
| 		f.wgLock.RUnlock() | ||||
| @@ -158,7 +163,7 @@ func (f *win32File) prepareIo() (*ioOperation, error) { | ||||
| 	return c, nil | ||||
| } | ||||
|  | ||||
| // ioCompletionProcessor processes completed async IOs forever | ||||
| // ioCompletionProcessor processes completed async IOs forever. | ||||
| func ioCompletionProcessor(h syscall.Handle) { | ||||
| 	for { | ||||
| 		var bytes uint32 | ||||
| @@ -172,15 +177,17 @@ func ioCompletionProcessor(h syscall.Handle) { | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // asyncIo processes the return value from ReadFile or WriteFile, blocking until | ||||
| // todo: helsaawy - create an asyncIO version that takes a context | ||||
|  | ||||
| // asyncIO processes the return value from ReadFile or WriteFile, blocking until | ||||
| // the operation has actually completed. | ||||
| func (f *win32File) asyncIo(c *ioOperation, d *deadlineHandler, bytes uint32, err error) (int, error) { | ||||
| 	if err != syscall.ERROR_IO_PENDING { | ||||
| func (f *win32File) asyncIO(c *ioOperation, d *deadlineHandler, bytes uint32, err error) (int, error) { | ||||
| 	if err != syscall.ERROR_IO_PENDING { //nolint:errorlint // err is Errno | ||||
| 		return int(bytes), err | ||||
| 	} | ||||
|  | ||||
| 	if f.closing.isSet() { | ||||
| 		cancelIoEx(f.handle, &c.o) | ||||
| 		_ = cancelIoEx(f.handle, &c.o) | ||||
| 	} | ||||
|  | ||||
| 	var timeout timeoutChan | ||||
| @@ -194,7 +201,7 @@ func (f *win32File) asyncIo(c *ioOperation, d *deadlineHandler, bytes uint32, er | ||||
| 	select { | ||||
| 	case r = <-c.ch: | ||||
| 		err = r.err | ||||
| 		if err == syscall.ERROR_OPERATION_ABORTED { | ||||
| 		if err == syscall.ERROR_OPERATION_ABORTED { //nolint:errorlint // err is Errno | ||||
| 			if f.closing.isSet() { | ||||
| 				err = ErrFileClosed | ||||
| 			} | ||||
| @@ -204,10 +211,10 @@ func (f *win32File) asyncIo(c *ioOperation, d *deadlineHandler, bytes uint32, er | ||||
| 			err = wsaGetOverlappedResult(f.handle, &c.o, &bytes, false, &flags) | ||||
| 		} | ||||
| 	case <-timeout: | ||||
| 		cancelIoEx(f.handle, &c.o) | ||||
| 		_ = cancelIoEx(f.handle, &c.o) | ||||
| 		r = <-c.ch | ||||
| 		err = r.err | ||||
| 		if err == syscall.ERROR_OPERATION_ABORTED { | ||||
| 		if err == syscall.ERROR_OPERATION_ABORTED { //nolint:errorlint // err is Errno | ||||
| 			err = ErrTimeout | ||||
| 		} | ||||
| 	} | ||||
| @@ -215,13 +222,14 @@ func (f *win32File) asyncIo(c *ioOperation, d *deadlineHandler, bytes uint32, er | ||||
| 	// runtime.KeepAlive is needed, as c is passed via native | ||||
| 	// code to ioCompletionProcessor, c must remain alive | ||||
| 	// until the channel read is complete. | ||||
| 	// todo: (de)allocate *ioOperation via win32 heap functions, instead of needing to KeepAlive? | ||||
| 	runtime.KeepAlive(c) | ||||
| 	return int(r.bytes), err | ||||
| } | ||||
|  | ||||
| // Read reads from a file handle. | ||||
| func (f *win32File) Read(b []byte) (int, error) { | ||||
| 	c, err := f.prepareIo() | ||||
| 	c, err := f.prepareIO() | ||||
| 	if err != nil { | ||||
| 		return 0, err | ||||
| 	} | ||||
| @@ -233,13 +241,13 @@ func (f *win32File) Read(b []byte) (int, error) { | ||||
|  | ||||
| 	var bytes uint32 | ||||
| 	err = syscall.ReadFile(f.handle, b, &bytes, &c.o) | ||||
| 	n, err := f.asyncIo(c, &f.readDeadline, bytes, err) | ||||
| 	n, err := f.asyncIO(c, &f.readDeadline, bytes, err) | ||||
| 	runtime.KeepAlive(b) | ||||
|  | ||||
| 	// Handle EOF conditions. | ||||
| 	if err == nil && n == 0 && len(b) != 0 { | ||||
| 		return 0, io.EOF | ||||
| 	} else if err == syscall.ERROR_BROKEN_PIPE { | ||||
| 	} else if err == syscall.ERROR_BROKEN_PIPE { //nolint:errorlint // err is Errno | ||||
| 		return 0, io.EOF | ||||
| 	} else { | ||||
| 		return n, err | ||||
| @@ -248,7 +256,7 @@ func (f *win32File) Read(b []byte) (int, error) { | ||||
|  | ||||
| // Write writes to a file handle. | ||||
| func (f *win32File) Write(b []byte) (int, error) { | ||||
| 	c, err := f.prepareIo() | ||||
| 	c, err := f.prepareIO() | ||||
| 	if err != nil { | ||||
| 		return 0, err | ||||
| 	} | ||||
| @@ -260,7 +268,7 @@ func (f *win32File) Write(b []byte) (int, error) { | ||||
|  | ||||
| 	var bytes uint32 | ||||
| 	err = syscall.WriteFile(f.handle, b, &bytes, &c.o) | ||||
| 	n, err := f.asyncIo(c, &f.writeDeadline, bytes, err) | ||||
| 	n, err := f.asyncIO(c, &f.writeDeadline, bytes, err) | ||||
| 	runtime.KeepAlive(b) | ||||
| 	return n, err | ||||
| } | ||||
|   | ||||
							
								
								
									
										29
									
								
								vendor/github.com/Microsoft/go-winio/fileinfo.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										29
									
								
								vendor/github.com/Microsoft/go-winio/fileinfo.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,3 +1,4 @@ | ||||
| //go:build windows | ||||
| // +build windows | ||||
|  | ||||
| package winio | ||||
| @@ -14,13 +15,18 @@ import ( | ||||
| type FileBasicInfo struct { | ||||
| 	CreationTime, LastAccessTime, LastWriteTime, ChangeTime windows.Filetime | ||||
| 	FileAttributes                                          uint32 | ||||
| 	pad                                                     uint32 // padding | ||||
| 	_                                                       uint32 // padding | ||||
| } | ||||
|  | ||||
| // GetFileBasicInfo retrieves times and attributes for a file. | ||||
| func GetFileBasicInfo(f *os.File) (*FileBasicInfo, error) { | ||||
| 	bi := &FileBasicInfo{} | ||||
| 	if err := windows.GetFileInformationByHandleEx(windows.Handle(f.Fd()), windows.FileBasicInfo, (*byte)(unsafe.Pointer(bi)), uint32(unsafe.Sizeof(*bi))); err != nil { | ||||
| 	if err := windows.GetFileInformationByHandleEx( | ||||
| 		windows.Handle(f.Fd()), | ||||
| 		windows.FileBasicInfo, | ||||
| 		(*byte)(unsafe.Pointer(bi)), | ||||
| 		uint32(unsafe.Sizeof(*bi)), | ||||
| 	); err != nil { | ||||
| 		return nil, &os.PathError{Op: "GetFileInformationByHandleEx", Path: f.Name(), Err: err} | ||||
| 	} | ||||
| 	runtime.KeepAlive(f) | ||||
| @@ -29,7 +35,12 @@ func GetFileBasicInfo(f *os.File) (*FileBasicInfo, error) { | ||||
|  | ||||
| // SetFileBasicInfo sets times and attributes for a file. | ||||
| func SetFileBasicInfo(f *os.File, bi *FileBasicInfo) error { | ||||
| 	if err := windows.SetFileInformationByHandle(windows.Handle(f.Fd()), windows.FileBasicInfo, (*byte)(unsafe.Pointer(bi)), uint32(unsafe.Sizeof(*bi))); err != nil { | ||||
| 	if err := windows.SetFileInformationByHandle( | ||||
| 		windows.Handle(f.Fd()), | ||||
| 		windows.FileBasicInfo, | ||||
| 		(*byte)(unsafe.Pointer(bi)), | ||||
| 		uint32(unsafe.Sizeof(*bi)), | ||||
| 	); err != nil { | ||||
| 		return &os.PathError{Op: "SetFileInformationByHandle", Path: f.Name(), Err: err} | ||||
| 	} | ||||
| 	runtime.KeepAlive(f) | ||||
| @@ -48,7 +59,10 @@ type FileStandardInfo struct { | ||||
| // GetFileStandardInfo retrieves ended information for the file. | ||||
| func GetFileStandardInfo(f *os.File) (*FileStandardInfo, error) { | ||||
| 	si := &FileStandardInfo{} | ||||
| 	if err := windows.GetFileInformationByHandleEx(windows.Handle(f.Fd()), windows.FileStandardInfo, (*byte)(unsafe.Pointer(si)), uint32(unsafe.Sizeof(*si))); err != nil { | ||||
| 	if err := windows.GetFileInformationByHandleEx(windows.Handle(f.Fd()), | ||||
| 		windows.FileStandardInfo, | ||||
| 		(*byte)(unsafe.Pointer(si)), | ||||
| 		uint32(unsafe.Sizeof(*si))); err != nil { | ||||
| 		return nil, &os.PathError{Op: "GetFileInformationByHandleEx", Path: f.Name(), Err: err} | ||||
| 	} | ||||
| 	runtime.KeepAlive(f) | ||||
| @@ -65,7 +79,12 @@ type FileIDInfo struct { | ||||
| // GetFileID retrieves the unique (volume, file ID) pair for a file. | ||||
| func GetFileID(f *os.File) (*FileIDInfo, error) { | ||||
| 	fileID := &FileIDInfo{} | ||||
| 	if err := windows.GetFileInformationByHandleEx(windows.Handle(f.Fd()), windows.FileIdInfo, (*byte)(unsafe.Pointer(fileID)), uint32(unsafe.Sizeof(*fileID))); err != nil { | ||||
| 	if err := windows.GetFileInformationByHandleEx( | ||||
| 		windows.Handle(f.Fd()), | ||||
| 		windows.FileIdInfo, | ||||
| 		(*byte)(unsafe.Pointer(fileID)), | ||||
| 		uint32(unsafe.Sizeof(*fileID)), | ||||
| 	); err != nil { | ||||
| 		return nil, &os.PathError{Op: "GetFileInformationByHandleEx", Path: f.Name(), Err: err} | ||||
| 	} | ||||
| 	runtime.KeepAlive(f) | ||||
|   | ||||
							
								
								
									
										360
									
								
								vendor/github.com/Microsoft/go-winio/hvsock.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										360
									
								
								vendor/github.com/Microsoft/go-winio/hvsock.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,8 +1,11 @@ | ||||
| //go:build windows | ||||
| // +build windows | ||||
|  | ||||
| package winio | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"io" | ||||
| 	"net" | ||||
| @@ -11,16 +14,87 @@ import ( | ||||
| 	"time" | ||||
| 	"unsafe" | ||||
|  | ||||
| 	"golang.org/x/sys/windows" | ||||
|  | ||||
| 	"github.com/Microsoft/go-winio/internal/socket" | ||||
| 	"github.com/Microsoft/go-winio/pkg/guid" | ||||
| ) | ||||
|  | ||||
| //sys bind(s syscall.Handle, name unsafe.Pointer, namelen int32) (err error) [failretval==socketError] = ws2_32.bind | ||||
| const afHVSock = 34 // AF_HYPERV | ||||
|  | ||||
| const ( | ||||
| 	afHvSock = 34 // AF_HYPERV | ||||
| // Well known Service and VM IDs | ||||
| //https://docs.microsoft.com/en-us/virtualization/hyper-v-on-windows/user-guide/make-integration-service#vmid-wildcards | ||||
|  | ||||
| 	socketError = ^uintptr(0) | ||||
| ) | ||||
| // HvsockGUIDWildcard is the wildcard VmId for accepting connections from all partitions. | ||||
| func HvsockGUIDWildcard() guid.GUID { // 00000000-0000-0000-0000-000000000000 | ||||
| 	return guid.GUID{} | ||||
| } | ||||
|  | ||||
| // HvsockGUIDBroadcast is the wildcard VmId for broadcasting sends to all partitions. | ||||
| func HvsockGUIDBroadcast() guid.GUID { //ffffffff-ffff-ffff-ffff-ffffffffffff | ||||
| 	return guid.GUID{ | ||||
| 		Data1: 0xffffffff, | ||||
| 		Data2: 0xffff, | ||||
| 		Data3: 0xffff, | ||||
| 		Data4: [8]uint8{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // HvsockGUIDLoopback is the Loopback VmId for accepting connections to the same partition as the connector. | ||||
| func HvsockGUIDLoopback() guid.GUID { // e0e16197-dd56-4a10-9195-5ee7a155a838 | ||||
| 	return guid.GUID{ | ||||
| 		Data1: 0xe0e16197, | ||||
| 		Data2: 0xdd56, | ||||
| 		Data3: 0x4a10, | ||||
| 		Data4: [8]uint8{0x91, 0x95, 0x5e, 0xe7, 0xa1, 0x55, 0xa8, 0x38}, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // HvsockGUIDSiloHost is the address of a silo's host partition: | ||||
| //   - The silo host of a hosted silo is the utility VM. | ||||
| //   - The silo host of a silo on a physical host is the physical host. | ||||
| func HvsockGUIDSiloHost() guid.GUID { // 36bd0c5c-7276-4223-88ba-7d03b654c568 | ||||
| 	return guid.GUID{ | ||||
| 		Data1: 0x36bd0c5c, | ||||
| 		Data2: 0x7276, | ||||
| 		Data3: 0x4223, | ||||
| 		Data4: [8]byte{0x88, 0xba, 0x7d, 0x03, 0xb6, 0x54, 0xc5, 0x68}, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // HvsockGUIDChildren is the wildcard VmId for accepting connections from the connector's child partitions. | ||||
| func HvsockGUIDChildren() guid.GUID { // 90db8b89-0d35-4f79-8ce9-49ea0ac8b7cd | ||||
| 	return guid.GUID{ | ||||
| 		Data1: 0x90db8b89, | ||||
| 		Data2: 0xd35, | ||||
| 		Data3: 0x4f79, | ||||
| 		Data4: [8]uint8{0x8c, 0xe9, 0x49, 0xea, 0xa, 0xc8, 0xb7, 0xcd}, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // HvsockGUIDParent is the wildcard VmId for accepting connections from the connector's parent partition. | ||||
| // Listening on this VmId accepts connection from: | ||||
| //   - Inside silos: silo host partition. | ||||
| //   - Inside hosted silo: host of the VM. | ||||
| //   - Inside VM: VM host. | ||||
| //   - Physical host: Not supported. | ||||
| func HvsockGUIDParent() guid.GUID { // a42e7cda-d03f-480c-9cc2-a4de20abb878 | ||||
| 	return guid.GUID{ | ||||
| 		Data1: 0xa42e7cda, | ||||
| 		Data2: 0xd03f, | ||||
| 		Data3: 0x480c, | ||||
| 		Data4: [8]uint8{0x9c, 0xc2, 0xa4, 0xde, 0x20, 0xab, 0xb8, 0x78}, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // hvsockVsockServiceTemplate is the Service GUID used for the VSOCK protocol. | ||||
| func hvsockVsockServiceTemplate() guid.GUID { // 00000000-facb-11e6-bd58-64006a7986d3 | ||||
| 	return guid.GUID{ | ||||
| 		Data2: 0xfacb, | ||||
| 		Data3: 0x11e6, | ||||
| 		Data4: [8]uint8{0xbd, 0x58, 0x64, 0x00, 0x6a, 0x79, 0x86, 0xd3}, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // An HvsockAddr is an address for a AF_HYPERV socket. | ||||
| type HvsockAddr struct { | ||||
| @@ -35,8 +109,10 @@ type rawHvsockAddr struct { | ||||
| 	ServiceID guid.GUID | ||||
| } | ||||
|  | ||||
| var _ socket.RawSockaddr = &rawHvsockAddr{} | ||||
|  | ||||
| // Network returns the address's network name, "hvsock". | ||||
| func (addr *HvsockAddr) Network() string { | ||||
| func (*HvsockAddr) Network() string { | ||||
| 	return "hvsock" | ||||
| } | ||||
|  | ||||
| @@ -46,14 +122,14 @@ func (addr *HvsockAddr) String() string { | ||||
|  | ||||
| // VsockServiceID returns an hvsock service ID corresponding to the specified AF_VSOCK port. | ||||
| func VsockServiceID(port uint32) guid.GUID { | ||||
| 	g, _ := guid.FromString("00000000-facb-11e6-bd58-64006a7986d3") | ||||
| 	g := hvsockVsockServiceTemplate() // make a copy | ||||
| 	g.Data1 = port | ||||
| 	return g | ||||
| } | ||||
|  | ||||
| func (addr *HvsockAddr) raw() rawHvsockAddr { | ||||
| 	return rawHvsockAddr{ | ||||
| 		Family:    afHvSock, | ||||
| 		Family:    afHVSock, | ||||
| 		VMID:      addr.VMID, | ||||
| 		ServiceID: addr.ServiceID, | ||||
| 	} | ||||
| @@ -64,20 +140,48 @@ func (addr *HvsockAddr) fromRaw(raw *rawHvsockAddr) { | ||||
| 	addr.ServiceID = raw.ServiceID | ||||
| } | ||||
|  | ||||
| // Sockaddr returns a pointer to and the size of this struct. | ||||
| // | ||||
| // Implements the [socket.RawSockaddr] interface, and allows use in | ||||
| // [socket.Bind] and [socket.ConnectEx]. | ||||
| func (r *rawHvsockAddr) Sockaddr() (unsafe.Pointer, int32, error) { | ||||
| 	return unsafe.Pointer(r), int32(unsafe.Sizeof(rawHvsockAddr{})), nil | ||||
| } | ||||
|  | ||||
| // Sockaddr interface allows use with `sockets.Bind()` and `.ConnectEx()`. | ||||
| func (r *rawHvsockAddr) FromBytes(b []byte) error { | ||||
| 	n := int(unsafe.Sizeof(rawHvsockAddr{})) | ||||
|  | ||||
| 	if len(b) < n { | ||||
| 		return fmt.Errorf("got %d, want %d: %w", len(b), n, socket.ErrBufferSize) | ||||
| 	} | ||||
|  | ||||
| 	copy(unsafe.Slice((*byte)(unsafe.Pointer(r)), n), b[:n]) | ||||
| 	if r.Family != afHVSock { | ||||
| 		return fmt.Errorf("got %d, want %d: %w", r.Family, afHVSock, socket.ErrAddrFamily) | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // HvsockListener is a socket listener for the AF_HYPERV address family. | ||||
| type HvsockListener struct { | ||||
| 	sock *win32File | ||||
| 	addr HvsockAddr | ||||
| } | ||||
|  | ||||
| var _ net.Listener = &HvsockListener{} | ||||
|  | ||||
| // HvsockConn is a connected socket of the AF_HYPERV address family. | ||||
| type HvsockConn struct { | ||||
| 	sock          *win32File | ||||
| 	local, remote HvsockAddr | ||||
| } | ||||
|  | ||||
| func newHvSocket() (*win32File, error) { | ||||
| 	fd, err := syscall.Socket(afHvSock, syscall.SOCK_STREAM, 1) | ||||
| var _ net.Conn = &HvsockConn{} | ||||
|  | ||||
| func newHVSocket() (*win32File, error) { | ||||
| 	fd, err := syscall.Socket(afHVSock, syscall.SOCK_STREAM, 1) | ||||
| 	if err != nil { | ||||
| 		return nil, os.NewSyscallError("socket", err) | ||||
| 	} | ||||
| @@ -93,12 +197,12 @@ func newHvSocket() (*win32File, error) { | ||||
| // ListenHvsock listens for connections on the specified hvsock address. | ||||
| func ListenHvsock(addr *HvsockAddr) (_ *HvsockListener, err error) { | ||||
| 	l := &HvsockListener{addr: *addr} | ||||
| 	sock, err := newHvSocket() | ||||
| 	sock, err := newHVSocket() | ||||
| 	if err != nil { | ||||
| 		return nil, l.opErr("listen", err) | ||||
| 	} | ||||
| 	sa := addr.raw() | ||||
| 	err = bind(sock.handle, unsafe.Pointer(&sa), int32(unsafe.Sizeof(sa))) | ||||
| 	err = socket.Bind(windows.Handle(sock.handle), &sa) | ||||
| 	if err != nil { | ||||
| 		return nil, l.opErr("listen", os.NewSyscallError("socket", err)) | ||||
| 	} | ||||
| @@ -120,7 +224,7 @@ func (l *HvsockListener) Addr() net.Addr { | ||||
|  | ||||
| // Accept waits for the next connection and returns it. | ||||
| func (l *HvsockListener) Accept() (_ net.Conn, err error) { | ||||
| 	sock, err := newHvSocket() | ||||
| 	sock, err := newHVSocket() | ||||
| 	if err != nil { | ||||
| 		return nil, l.opErr("accept", err) | ||||
| 	} | ||||
| @@ -129,27 +233,42 @@ func (l *HvsockListener) Accept() (_ net.Conn, err error) { | ||||
| 			sock.Close() | ||||
| 		} | ||||
| 	}() | ||||
| 	c, err := l.sock.prepareIo() | ||||
| 	c, err := l.sock.prepareIO() | ||||
| 	if err != nil { | ||||
| 		return nil, l.opErr("accept", err) | ||||
| 	} | ||||
| 	defer l.sock.wg.Done() | ||||
|  | ||||
| 	// AcceptEx, per documentation, requires an extra 16 bytes per address. | ||||
| 	// | ||||
| 	// https://docs.microsoft.com/en-us/windows/win32/api/mswsock/nf-mswsock-acceptex | ||||
| 	const addrlen = uint32(16 + unsafe.Sizeof(rawHvsockAddr{})) | ||||
| 	var addrbuf [addrlen * 2]byte | ||||
|  | ||||
| 	var bytes uint32 | ||||
| 	err = syscall.AcceptEx(l.sock.handle, sock.handle, &addrbuf[0], 0, addrlen, addrlen, &bytes, &c.o) | ||||
| 	_, err = l.sock.asyncIo(c, nil, bytes, err) | ||||
| 	if err != nil { | ||||
| 	err = syscall.AcceptEx(l.sock.handle, sock.handle, &addrbuf[0], 0 /*rxdatalen*/, addrlen, addrlen, &bytes, &c.o) | ||||
| 	if _, err = l.sock.asyncIO(c, nil, bytes, err); err != nil { | ||||
| 		return nil, l.opErr("accept", os.NewSyscallError("acceptex", err)) | ||||
| 	} | ||||
|  | ||||
| 	conn := &HvsockConn{ | ||||
| 		sock: sock, | ||||
| 	} | ||||
| 	// The local address returned in the AcceptEx buffer is the same as the Listener socket's | ||||
| 	// address. However, the service GUID reported by GetSockName is different from the Listeners | ||||
| 	// socket, and is sometimes the same as the local address of the socket that dialed the | ||||
| 	// address, with the service GUID.Data1 incremented, but othertimes is different. | ||||
| 	// todo: does the local address matter? is the listener's address or the actual address appropriate? | ||||
| 	conn.local.fromRaw((*rawHvsockAddr)(unsafe.Pointer(&addrbuf[0]))) | ||||
| 	conn.remote.fromRaw((*rawHvsockAddr)(unsafe.Pointer(&addrbuf[addrlen]))) | ||||
|  | ||||
| 	// initialize the accepted socket and update its properties with those of the listening socket | ||||
| 	if err = windows.Setsockopt(windows.Handle(sock.handle), | ||||
| 		windows.SOL_SOCKET, windows.SO_UPDATE_ACCEPT_CONTEXT, | ||||
| 		(*byte)(unsafe.Pointer(&l.sock.handle)), int32(unsafe.Sizeof(l.sock.handle))); err != nil { | ||||
| 		return nil, conn.opErr("accept", os.NewSyscallError("setsockopt", err)) | ||||
| 	} | ||||
|  | ||||
| 	sock = nil | ||||
| 	return conn, nil | ||||
| } | ||||
| @@ -159,43 +278,171 @@ func (l *HvsockListener) Close() error { | ||||
| 	return l.sock.Close() | ||||
| } | ||||
|  | ||||
| /* Need to finish ConnectEx handling | ||||
| func DialHvsock(ctx context.Context, addr *HvsockAddr) (*HvsockConn, error) { | ||||
| 	sock, err := newHvSocket() | ||||
| // HvsockDialer configures and dials a Hyper-V Socket (ie, [HvsockConn]). | ||||
| type HvsockDialer struct { | ||||
| 	// Deadline is the time the Dial operation must connect before erroring. | ||||
| 	Deadline time.Time | ||||
|  | ||||
| 	// Retries is the number of additional connects to try if the connection times out, is refused, | ||||
| 	// or the host is unreachable | ||||
| 	Retries uint | ||||
|  | ||||
| 	// RetryWait is the time to wait after a connection error to retry | ||||
| 	RetryWait time.Duration | ||||
|  | ||||
| 	rt *time.Timer // redial wait timer | ||||
| } | ||||
|  | ||||
| // Dial the Hyper-V socket at addr. | ||||
| // | ||||
| // See [HvsockDialer.Dial] for more information. | ||||
| func Dial(ctx context.Context, addr *HvsockAddr) (conn *HvsockConn, err error) { | ||||
| 	return (&HvsockDialer{}).Dial(ctx, addr) | ||||
| } | ||||
|  | ||||
| // Dial attempts to connect to the Hyper-V socket at addr, and returns a connection if successful. | ||||
| // Will attempt (HvsockDialer).Retries if dialing fails, waiting (HvsockDialer).RetryWait between | ||||
| // retries. | ||||
| // | ||||
| // Dialing can be cancelled either by providing (HvsockDialer).Deadline, or cancelling ctx. | ||||
| func (d *HvsockDialer) Dial(ctx context.Context, addr *HvsockAddr) (conn *HvsockConn, err error) { | ||||
| 	op := "dial" | ||||
| 	// create the conn early to use opErr() | ||||
| 	conn = &HvsockConn{ | ||||
| 		remote: *addr, | ||||
| 	} | ||||
|  | ||||
| 	if !d.Deadline.IsZero() { | ||||
| 		var cancel context.CancelFunc | ||||
| 		ctx, cancel = context.WithDeadline(ctx, d.Deadline) | ||||
| 		defer cancel() | ||||
| 	} | ||||
|  | ||||
| 	// preemptive timeout/cancellation check | ||||
| 	if err = ctx.Err(); err != nil { | ||||
| 		return nil, conn.opErr(op, err) | ||||
| 	} | ||||
|  | ||||
| 	sock, err := newHVSocket() | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 		return nil, conn.opErr(op, err) | ||||
| 	} | ||||
| 	defer func() { | ||||
| 		if sock != nil { | ||||
| 			sock.Close() | ||||
| 		} | ||||
| 	}() | ||||
| 	c, err := sock.prepareIo() | ||||
|  | ||||
| 	sa := addr.raw() | ||||
| 	err = socket.Bind(windows.Handle(sock.handle), &sa) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 		return nil, conn.opErr(op, os.NewSyscallError("bind", err)) | ||||
| 	} | ||||
|  | ||||
| 	c, err := sock.prepareIO() | ||||
| 	if err != nil { | ||||
| 		return nil, conn.opErr(op, err) | ||||
| 	} | ||||
| 	defer sock.wg.Done() | ||||
| 	var bytes uint32 | ||||
| 	err = windows.ConnectEx(windows.Handle(sock.handle), sa, nil, 0, &bytes, &c.o) | ||||
| 	_, err = sock.asyncIo(ctx, c, nil, bytes, err) | ||||
| 	for i := uint(0); i <= d.Retries; i++ { | ||||
| 		err = socket.ConnectEx( | ||||
| 			windows.Handle(sock.handle), | ||||
| 			&sa, | ||||
| 			nil, // sendBuf | ||||
| 			0,   // sendDataLen | ||||
| 			&bytes, | ||||
| 			(*windows.Overlapped)(unsafe.Pointer(&c.o))) | ||||
| 		_, err = sock.asyncIO(c, nil, bytes, err) | ||||
| 		if i < d.Retries && canRedial(err) { | ||||
| 			if err = d.redialWait(ctx); err == nil { | ||||
| 				continue | ||||
| 			} | ||||
| 		} | ||||
| 		break | ||||
| 	} | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 		return nil, conn.opErr(op, os.NewSyscallError("connectex", err)) | ||||
| 	} | ||||
| 	conn := &HvsockConn{ | ||||
| 		sock:   sock, | ||||
| 		remote: *addr, | ||||
|  | ||||
| 	// update the connection properties, so shutdown can be used | ||||
| 	if err = windows.Setsockopt( | ||||
| 		windows.Handle(sock.handle), | ||||
| 		windows.SOL_SOCKET, | ||||
| 		windows.SO_UPDATE_CONNECT_CONTEXT, | ||||
| 		nil, // optvalue | ||||
| 		0,   // optlen | ||||
| 	); err != nil { | ||||
| 		return nil, conn.opErr(op, os.NewSyscallError("setsockopt", err)) | ||||
| 	} | ||||
|  | ||||
| 	// get the local name | ||||
| 	var sal rawHvsockAddr | ||||
| 	err = socket.GetSockName(windows.Handle(sock.handle), &sal) | ||||
| 	if err != nil { | ||||
| 		return nil, conn.opErr(op, os.NewSyscallError("getsockname", err)) | ||||
| 	} | ||||
| 	conn.local.fromRaw(&sal) | ||||
|  | ||||
| 	// one last check for timeout, since asyncIO doesn't check the context | ||||
| 	if err = ctx.Err(); err != nil { | ||||
| 		return nil, conn.opErr(op, err) | ||||
| 	} | ||||
|  | ||||
| 	conn.sock = sock | ||||
| 	sock = nil | ||||
|  | ||||
| 	return conn, nil | ||||
| } | ||||
| */ | ||||
|  | ||||
| // redialWait waits before attempting to redial, resetting the timer as appropriate. | ||||
| func (d *HvsockDialer) redialWait(ctx context.Context) (err error) { | ||||
| 	if d.RetryWait == 0 { | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| 	if d.rt == nil { | ||||
| 		d.rt = time.NewTimer(d.RetryWait) | ||||
| 	} else { | ||||
| 		// should already be stopped and drained | ||||
| 		d.rt.Reset(d.RetryWait) | ||||
| 	} | ||||
|  | ||||
| 	select { | ||||
| 	case <-ctx.Done(): | ||||
| 	case <-d.rt.C: | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| 	// stop and drain the timer | ||||
| 	if !d.rt.Stop() { | ||||
| 		<-d.rt.C | ||||
| 	} | ||||
| 	return ctx.Err() | ||||
| } | ||||
|  | ||||
| // assumes error is a plain, unwrapped syscall.Errno provided by direct syscall. | ||||
| func canRedial(err error) bool { | ||||
| 	//nolint:errorlint // guaranteed to be an Errno | ||||
| 	switch err { | ||||
| 	case windows.WSAECONNREFUSED, windows.WSAENETUNREACH, windows.WSAETIMEDOUT, | ||||
| 		windows.ERROR_CONNECTION_REFUSED, windows.ERROR_CONNECTION_UNAVAIL: | ||||
| 		return true | ||||
| 	default: | ||||
| 		return false | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (conn *HvsockConn) opErr(op string, err error) error { | ||||
| 	// translate from "file closed" to "socket closed" | ||||
| 	if errors.Is(err, ErrFileClosed) { | ||||
| 		err = socket.ErrSocketClosed | ||||
| 	} | ||||
| 	return &net.OpError{Op: op, Net: "hvsock", Source: &conn.local, Addr: &conn.remote, Err: err} | ||||
| } | ||||
|  | ||||
| func (conn *HvsockConn) Read(b []byte) (int, error) { | ||||
| 	c, err := conn.sock.prepareIo() | ||||
| 	c, err := conn.sock.prepareIO() | ||||
| 	if err != nil { | ||||
| 		return 0, conn.opErr("read", err) | ||||
| 	} | ||||
| @@ -203,10 +450,11 @@ func (conn *HvsockConn) Read(b []byte) (int, error) { | ||||
| 	buf := syscall.WSABuf{Buf: &b[0], Len: uint32(len(b))} | ||||
| 	var flags, bytes uint32 | ||||
| 	err = syscall.WSARecv(conn.sock.handle, &buf, 1, &bytes, &flags, &c.o, nil) | ||||
| 	n, err := conn.sock.asyncIo(c, &conn.sock.readDeadline, bytes, err) | ||||
| 	n, err := conn.sock.asyncIO(c, &conn.sock.readDeadline, bytes, err) | ||||
| 	if err != nil { | ||||
| 		if _, ok := err.(syscall.Errno); ok { | ||||
| 			err = os.NewSyscallError("wsarecv", err) | ||||
| 		var eno windows.Errno | ||||
| 		if errors.As(err, &eno) { | ||||
| 			err = os.NewSyscallError("wsarecv", eno) | ||||
| 		} | ||||
| 		return 0, conn.opErr("read", err) | ||||
| 	} else if n == 0 { | ||||
| @@ -229,7 +477,7 @@ func (conn *HvsockConn) Write(b []byte) (int, error) { | ||||
| } | ||||
|  | ||||
| func (conn *HvsockConn) write(b []byte) (int, error) { | ||||
| 	c, err := conn.sock.prepareIo() | ||||
| 	c, err := conn.sock.prepareIO() | ||||
| 	if err != nil { | ||||
| 		return 0, conn.opErr("write", err) | ||||
| 	} | ||||
| @@ -237,10 +485,11 @@ func (conn *HvsockConn) write(b []byte) (int, error) { | ||||
| 	buf := syscall.WSABuf{Buf: &b[0], Len: uint32(len(b))} | ||||
| 	var bytes uint32 | ||||
| 	err = syscall.WSASend(conn.sock.handle, &buf, 1, &bytes, 0, &c.o, nil) | ||||
| 	n, err := conn.sock.asyncIo(c, &conn.sock.writeDeadline, bytes, err) | ||||
| 	n, err := conn.sock.asyncIO(c, &conn.sock.writeDeadline, bytes, err) | ||||
| 	if err != nil { | ||||
| 		if _, ok := err.(syscall.Errno); ok { | ||||
| 			err = os.NewSyscallError("wsasend", err) | ||||
| 		var eno windows.Errno | ||||
| 		if errors.As(err, &eno) { | ||||
| 			err = os.NewSyscallError("wsasend", eno) | ||||
| 		} | ||||
| 		return 0, conn.opErr("write", err) | ||||
| 	} | ||||
| @@ -252,29 +501,43 @@ func (conn *HvsockConn) Close() error { | ||||
| 	return conn.sock.Close() | ||||
| } | ||||
|  | ||||
| func (conn *HvsockConn) IsClosed() bool { | ||||
| 	return conn.sock.IsClosed() | ||||
| } | ||||
|  | ||||
| // shutdown disables sending or receiving on a socket. | ||||
| func (conn *HvsockConn) shutdown(how int) error { | ||||
| 	err := syscall.Shutdown(conn.sock.handle, syscall.SHUT_RD) | ||||
| 	if conn.IsClosed() { | ||||
| 		return socket.ErrSocketClosed | ||||
| 	} | ||||
|  | ||||
| 	err := syscall.Shutdown(conn.sock.handle, how) | ||||
| 	if err != nil { | ||||
| 		// If the connection was closed, shutdowns fail with "not connected" | ||||
| 		if errors.Is(err, windows.WSAENOTCONN) || | ||||
| 			errors.Is(err, windows.WSAESHUTDOWN) { | ||||
| 			err = socket.ErrSocketClosed | ||||
| 		} | ||||
| 		return os.NewSyscallError("shutdown", err) | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // CloseRead shuts down the read end of the socket. | ||||
| // CloseRead shuts down the read end of the socket, preventing future read operations. | ||||
| func (conn *HvsockConn) CloseRead() error { | ||||
| 	err := conn.shutdown(syscall.SHUT_RD) | ||||
| 	if err != nil { | ||||
| 		return conn.opErr("close", err) | ||||
| 		return conn.opErr("closeread", err) | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // CloseWrite shuts down the write end of the socket, notifying the other endpoint that | ||||
| // no more data will be written. | ||||
| // CloseWrite shuts down the write end of the socket, preventing future write operations and | ||||
| // notifying the other endpoint that no more data will be written. | ||||
| func (conn *HvsockConn) CloseWrite() error { | ||||
| 	err := conn.shutdown(syscall.SHUT_WR) | ||||
| 	if err != nil { | ||||
| 		return conn.opErr("close", err) | ||||
| 		return conn.opErr("closewrite", err) | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| @@ -291,8 +554,13 @@ func (conn *HvsockConn) RemoteAddr() net.Addr { | ||||
|  | ||||
| // SetDeadline implements the net.Conn SetDeadline method. | ||||
| func (conn *HvsockConn) SetDeadline(t time.Time) error { | ||||
| 	conn.SetReadDeadline(t) | ||||
| 	conn.SetWriteDeadline(t) | ||||
| 	// todo: implement `SetDeadline` for `win32File` | ||||
| 	if err := conn.SetReadDeadline(t); err != nil { | ||||
| 		return fmt.Errorf("set read deadline: %w", err) | ||||
| 	} | ||||
| 	if err := conn.SetWriteDeadline(t); err != nil { | ||||
| 		return fmt.Errorf("set write deadline: %w", err) | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
|   | ||||
							
								
								
									
										20
									
								
								vendor/github.com/Microsoft/go-winio/internal/socket/rawaddr.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								vendor/github.com/Microsoft/go-winio/internal/socket/rawaddr.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,20 @@ | ||||
| package socket | ||||
|  | ||||
| import ( | ||||
| 	"unsafe" | ||||
| ) | ||||
|  | ||||
| // RawSockaddr allows structs to be used with [Bind] and [ConnectEx]. The | ||||
| // struct must meet the Win32 sockaddr requirements specified here: | ||||
| // https://docs.microsoft.com/en-us/windows/win32/winsock/sockaddr-2 | ||||
| // | ||||
| // Specifically, the struct size must be least larger than an int16 (unsigned short) | ||||
| // for the address family. | ||||
| type RawSockaddr interface { | ||||
| 	// Sockaddr returns a pointer to the RawSockaddr and its struct size, allowing | ||||
| 	// for the RawSockaddr's data to be overwritten by syscalls (if necessary). | ||||
| 	// | ||||
| 	// It is the callers responsibility to validate that the values are valid; invalid | ||||
| 	// pointers or size can cause a panic. | ||||
| 	Sockaddr() (unsafe.Pointer, int32, error) | ||||
| } | ||||
							
								
								
									
										179
									
								
								vendor/github.com/Microsoft/go-winio/internal/socket/socket.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										179
									
								
								vendor/github.com/Microsoft/go-winio/internal/socket/socket.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,179 @@ | ||||
| //go:build windows | ||||
|  | ||||
| package socket | ||||
|  | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"net" | ||||
| 	"sync" | ||||
| 	"syscall" | ||||
| 	"unsafe" | ||||
|  | ||||
| 	"github.com/Microsoft/go-winio/pkg/guid" | ||||
| 	"golang.org/x/sys/windows" | ||||
| ) | ||||
|  | ||||
| //go:generate go run github.com/Microsoft/go-winio/tools/mkwinsyscall -output zsyscall_windows.go socket.go | ||||
|  | ||||
| //sys getsockname(s windows.Handle, name unsafe.Pointer, namelen *int32) (err error) [failretval==socketError] = ws2_32.getsockname | ||||
| //sys getpeername(s windows.Handle, name unsafe.Pointer, namelen *int32) (err error) [failretval==socketError] = ws2_32.getpeername | ||||
| //sys bind(s windows.Handle, name unsafe.Pointer, namelen int32) (err error) [failretval==socketError] = ws2_32.bind | ||||
|  | ||||
| const socketError = uintptr(^uint32(0)) | ||||
|  | ||||
| var ( | ||||
| 	// todo(helsaawy): create custom error types to store the desired vs actual size and addr family? | ||||
|  | ||||
| 	ErrBufferSize     = errors.New("buffer size") | ||||
| 	ErrAddrFamily     = errors.New("address family") | ||||
| 	ErrInvalidPointer = errors.New("invalid pointer") | ||||
| 	ErrSocketClosed   = fmt.Errorf("socket closed: %w", net.ErrClosed) | ||||
| ) | ||||
|  | ||||
| // todo(helsaawy): replace these with generics, ie: GetSockName[S RawSockaddr](s windows.Handle) (S, error) | ||||
|  | ||||
| // GetSockName writes the local address of socket s to the [RawSockaddr] rsa. | ||||
| // If rsa is not large enough, the [windows.WSAEFAULT] is returned. | ||||
| func GetSockName(s windows.Handle, rsa RawSockaddr) error { | ||||
| 	ptr, l, err := rsa.Sockaddr() | ||||
| 	if err != nil { | ||||
| 		return fmt.Errorf("could not retrieve socket pointer and size: %w", err) | ||||
| 	} | ||||
|  | ||||
| 	// although getsockname returns WSAEFAULT if the buffer is too small, it does not set | ||||
| 	// &l to the correct size, so--apart from doubling the buffer repeatedly--there is no remedy | ||||
| 	return getsockname(s, ptr, &l) | ||||
| } | ||||
|  | ||||
| // GetPeerName returns the remote address the socket is connected to. | ||||
| // | ||||
| // See [GetSockName] for more information. | ||||
| func GetPeerName(s windows.Handle, rsa RawSockaddr) error { | ||||
| 	ptr, l, err := rsa.Sockaddr() | ||||
| 	if err != nil { | ||||
| 		return fmt.Errorf("could not retrieve socket pointer and size: %w", err) | ||||
| 	} | ||||
|  | ||||
| 	return getpeername(s, ptr, &l) | ||||
| } | ||||
|  | ||||
| func Bind(s windows.Handle, rsa RawSockaddr) (err error) { | ||||
| 	ptr, l, err := rsa.Sockaddr() | ||||
| 	if err != nil { | ||||
| 		return fmt.Errorf("could not retrieve socket pointer and size: %w", err) | ||||
| 	} | ||||
|  | ||||
| 	return bind(s, ptr, l) | ||||
| } | ||||
|  | ||||
| // "golang.org/x/sys/windows".ConnectEx and .Bind only accept internal implementations of the | ||||
| // their sockaddr interface, so they cannot be used with HvsockAddr | ||||
| // Replicate functionality here from | ||||
| // https://cs.opensource.google/go/x/sys/+/master:windows/syscall_windows.go | ||||
|  | ||||
| // The function pointers to `AcceptEx`, `ConnectEx` and `GetAcceptExSockaddrs` must be loaded at | ||||
| // runtime via a WSAIoctl call: | ||||
| // https://docs.microsoft.com/en-us/windows/win32/api/Mswsock/nc-mswsock-lpfn_connectex#remarks | ||||
|  | ||||
| type runtimeFunc struct { | ||||
| 	id   guid.GUID | ||||
| 	once sync.Once | ||||
| 	addr uintptr | ||||
| 	err  error | ||||
| } | ||||
|  | ||||
| func (f *runtimeFunc) Load() error { | ||||
| 	f.once.Do(func() { | ||||
| 		var s windows.Handle | ||||
| 		s, f.err = windows.Socket(windows.AF_INET, windows.SOCK_STREAM, windows.IPPROTO_TCP) | ||||
| 		if f.err != nil { | ||||
| 			return | ||||
| 		} | ||||
| 		defer windows.CloseHandle(s) //nolint:errcheck | ||||
|  | ||||
| 		var n uint32 | ||||
| 		f.err = windows.WSAIoctl(s, | ||||
| 			windows.SIO_GET_EXTENSION_FUNCTION_POINTER, | ||||
| 			(*byte)(unsafe.Pointer(&f.id)), | ||||
| 			uint32(unsafe.Sizeof(f.id)), | ||||
| 			(*byte)(unsafe.Pointer(&f.addr)), | ||||
| 			uint32(unsafe.Sizeof(f.addr)), | ||||
| 			&n, | ||||
| 			nil, //overlapped | ||||
| 			0,   //completionRoutine | ||||
| 		) | ||||
| 	}) | ||||
| 	return f.err | ||||
| } | ||||
|  | ||||
| var ( | ||||
| 	// todo: add `AcceptEx` and `GetAcceptExSockaddrs` | ||||
| 	WSAID_CONNECTEX = guid.GUID{ //revive:disable-line:var-naming ALL_CAPS | ||||
| 		Data1: 0x25a207b9, | ||||
| 		Data2: 0xddf3, | ||||
| 		Data3: 0x4660, | ||||
| 		Data4: [8]byte{0x8e, 0xe9, 0x76, 0xe5, 0x8c, 0x74, 0x06, 0x3e}, | ||||
| 	} | ||||
|  | ||||
| 	connectExFunc = runtimeFunc{id: WSAID_CONNECTEX} | ||||
| ) | ||||
|  | ||||
| func ConnectEx( | ||||
| 	fd windows.Handle, | ||||
| 	rsa RawSockaddr, | ||||
| 	sendBuf *byte, | ||||
| 	sendDataLen uint32, | ||||
| 	bytesSent *uint32, | ||||
| 	overlapped *windows.Overlapped, | ||||
| ) error { | ||||
| 	if err := connectExFunc.Load(); err != nil { | ||||
| 		return fmt.Errorf("failed to load ConnectEx function pointer: %w", err) | ||||
| 	} | ||||
| 	ptr, n, err := rsa.Sockaddr() | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return connectEx(fd, ptr, n, sendBuf, sendDataLen, bytesSent, overlapped) | ||||
| } | ||||
|  | ||||
| // BOOL LpfnConnectex( | ||||
| //   [in]           SOCKET s, | ||||
| //   [in]           const sockaddr *name, | ||||
| //   [in]           int namelen, | ||||
| //   [in, optional] PVOID lpSendBuffer, | ||||
| //   [in]           DWORD dwSendDataLength, | ||||
| //   [out]          LPDWORD lpdwBytesSent, | ||||
| //   [in]           LPOVERLAPPED lpOverlapped | ||||
| // ) | ||||
|  | ||||
| func connectEx( | ||||
| 	s windows.Handle, | ||||
| 	name unsafe.Pointer, | ||||
| 	namelen int32, | ||||
| 	sendBuf *byte, | ||||
| 	sendDataLen uint32, | ||||
| 	bytesSent *uint32, | ||||
| 	overlapped *windows.Overlapped, | ||||
| ) (err error) { | ||||
| 	// todo: after upgrading to 1.18, switch from syscall.Syscall9 to syscall.SyscallN | ||||
| 	r1, _, e1 := syscall.Syscall9(connectExFunc.addr, | ||||
| 		7, | ||||
| 		uintptr(s), | ||||
| 		uintptr(name), | ||||
| 		uintptr(namelen), | ||||
| 		uintptr(unsafe.Pointer(sendBuf)), | ||||
| 		uintptr(sendDataLen), | ||||
| 		uintptr(unsafe.Pointer(bytesSent)), | ||||
| 		uintptr(unsafe.Pointer(overlapped)), | ||||
| 		0, | ||||
| 		0) | ||||
| 	if r1 == 0 { | ||||
| 		if e1 != 0 { | ||||
| 			err = error(e1) | ||||
| 		} else { | ||||
| 			err = syscall.EINVAL | ||||
| 		} | ||||
| 	} | ||||
| 	return err | ||||
| } | ||||
							
								
								
									
										72
									
								
								vendor/github.com/Microsoft/go-winio/internal/socket/zsyscall_windows.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								vendor/github.com/Microsoft/go-winio/internal/socket/zsyscall_windows.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,72 @@ | ||||
| //go:build windows | ||||
|  | ||||
| // Code generated by 'go generate' using "github.com/Microsoft/go-winio/tools/mkwinsyscall"; DO NOT EDIT. | ||||
|  | ||||
| package socket | ||||
|  | ||||
| import ( | ||||
| 	"syscall" | ||||
| 	"unsafe" | ||||
|  | ||||
| 	"golang.org/x/sys/windows" | ||||
| ) | ||||
|  | ||||
| var _ unsafe.Pointer | ||||
|  | ||||
| // Do the interface allocations only once for common | ||||
| // Errno values. | ||||
| const ( | ||||
| 	errnoERROR_IO_PENDING = 997 | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| 	errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING) | ||||
| 	errERROR_EINVAL     error = syscall.EINVAL | ||||
| ) | ||||
|  | ||||
| // errnoErr returns common boxed Errno values, to prevent | ||||
| // allocations at runtime. | ||||
| func errnoErr(e syscall.Errno) error { | ||||
| 	switch e { | ||||
| 	case 0: | ||||
| 		return errERROR_EINVAL | ||||
| 	case errnoERROR_IO_PENDING: | ||||
| 		return errERROR_IO_PENDING | ||||
| 	} | ||||
| 	// TODO: add more here, after collecting data on the common | ||||
| 	// error values see on Windows. (perhaps when running | ||||
| 	// all.bat?) | ||||
| 	return e | ||||
| } | ||||
|  | ||||
| var ( | ||||
| 	modws2_32 = windows.NewLazySystemDLL("ws2_32.dll") | ||||
|  | ||||
| 	procbind        = modws2_32.NewProc("bind") | ||||
| 	procgetpeername = modws2_32.NewProc("getpeername") | ||||
| 	procgetsockname = modws2_32.NewProc("getsockname") | ||||
| ) | ||||
|  | ||||
| func bind(s windows.Handle, name unsafe.Pointer, namelen int32) (err error) { | ||||
| 	r1, _, e1 := syscall.Syscall(procbind.Addr(), 3, uintptr(s), uintptr(name), uintptr(namelen)) | ||||
| 	if r1 == socketError { | ||||
| 		err = errnoErr(e1) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
|  | ||||
| func getpeername(s windows.Handle, name unsafe.Pointer, namelen *int32) (err error) { | ||||
| 	r1, _, e1 := syscall.Syscall(procgetpeername.Addr(), 3, uintptr(s), uintptr(name), uintptr(unsafe.Pointer(namelen))) | ||||
| 	if r1 == socketError { | ||||
| 		err = errnoErr(e1) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
|  | ||||
| func getsockname(s windows.Handle, name unsafe.Pointer, namelen *int32) (err error) { | ||||
| 	r1, _, e1 := syscall.Syscall(procgetsockname.Addr(), 3, uintptr(s), uintptr(name), uintptr(unsafe.Pointer(namelen))) | ||||
| 	if r1 == socketError { | ||||
| 		err = errnoErr(e1) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
							
								
								
									
										124
									
								
								vendor/github.com/Microsoft/go-winio/pipe.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										124
									
								
								vendor/github.com/Microsoft/go-winio/pipe.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,3 +1,4 @@ | ||||
| //go:build windows | ||||
| // +build windows | ||||
|  | ||||
| package winio | ||||
| @@ -13,6 +14,8 @@ import ( | ||||
| 	"syscall" | ||||
| 	"time" | ||||
| 	"unsafe" | ||||
|  | ||||
| 	"golang.org/x/sys/windows" | ||||
| ) | ||||
|  | ||||
| //sys connectNamedPipe(pipe syscall.Handle, o *syscall.Overlapped) (err error) = ConnectNamedPipe | ||||
| @@ -21,10 +24,10 @@ import ( | ||||
| //sys getNamedPipeInfo(pipe syscall.Handle, flags *uint32, outSize *uint32, inSize *uint32, maxInstances *uint32) (err error) = GetNamedPipeInfo | ||||
| //sys getNamedPipeHandleState(pipe syscall.Handle, state *uint32, curInstances *uint32, maxCollectionCount *uint32, collectDataTimeout *uint32, userName *uint16, maxUserNameSize uint32) (err error) = GetNamedPipeHandleStateW | ||||
| //sys localAlloc(uFlags uint32, length uint32) (ptr uintptr) = LocalAlloc | ||||
| //sys ntCreateNamedPipeFile(pipe *syscall.Handle, access uint32, oa *objectAttributes, iosb *ioStatusBlock, share uint32, disposition uint32, options uint32, typ uint32, readMode uint32, completionMode uint32, maxInstances uint32, inboundQuota uint32, outputQuota uint32, timeout *int64) (status ntstatus) = ntdll.NtCreateNamedPipeFile | ||||
| //sys rtlNtStatusToDosError(status ntstatus) (winerr error) = ntdll.RtlNtStatusToDosErrorNoTeb | ||||
| //sys rtlDosPathNameToNtPathName(name *uint16, ntName *unicodeString, filePart uintptr, reserved uintptr) (status ntstatus) = ntdll.RtlDosPathNameToNtPathName_U | ||||
| //sys rtlDefaultNpAcl(dacl *uintptr) (status ntstatus) = ntdll.RtlDefaultNpAcl | ||||
| //sys ntCreateNamedPipeFile(pipe *syscall.Handle, access uint32, oa *objectAttributes, iosb *ioStatusBlock, share uint32, disposition uint32, options uint32, typ uint32, readMode uint32, completionMode uint32, maxInstances uint32, inboundQuota uint32, outputQuota uint32, timeout *int64) (status ntStatus) = ntdll.NtCreateNamedPipeFile | ||||
| //sys rtlNtStatusToDosError(status ntStatus) (winerr error) = ntdll.RtlNtStatusToDosErrorNoTeb | ||||
| //sys rtlDosPathNameToNtPathName(name *uint16, ntName *unicodeString, filePart uintptr, reserved uintptr) (status ntStatus) = ntdll.RtlDosPathNameToNtPathName_U | ||||
| //sys rtlDefaultNpAcl(dacl *uintptr) (status ntStatus) = ntdll.RtlDefaultNpAcl | ||||
|  | ||||
| type ioStatusBlock struct { | ||||
| 	Status, Information uintptr | ||||
| @@ -51,45 +54,22 @@ type securityDescriptor struct { | ||||
| 	Control  uint16 | ||||
| 	Owner    uintptr | ||||
| 	Group    uintptr | ||||
| 	Sacl     uintptr | ||||
| 	Dacl     uintptr | ||||
| 	Sacl     uintptr //revive:disable-line:var-naming SACL, not Sacl | ||||
| 	Dacl     uintptr //revive:disable-line:var-naming DACL, not Dacl | ||||
| } | ||||
|  | ||||
| type ntstatus int32 | ||||
| type ntStatus int32 | ||||
|  | ||||
| func (status ntstatus) Err() error { | ||||
| func (status ntStatus) Err() error { | ||||
| 	if status >= 0 { | ||||
| 		return nil | ||||
| 	} | ||||
| 	return rtlNtStatusToDosError(status) | ||||
| } | ||||
|  | ||||
| const ( | ||||
| 	cERROR_PIPE_BUSY      = syscall.Errno(231) | ||||
| 	cERROR_NO_DATA        = syscall.Errno(232) | ||||
| 	cERROR_PIPE_CONNECTED = syscall.Errno(535) | ||||
| 	cERROR_SEM_TIMEOUT    = syscall.Errno(121) | ||||
|  | ||||
| 	cSECURITY_SQOS_PRESENT = 0x100000 | ||||
| 	cSECURITY_ANONYMOUS    = 0 | ||||
|  | ||||
| 	cPIPE_TYPE_MESSAGE = 4 | ||||
|  | ||||
| 	cPIPE_READMODE_MESSAGE = 2 | ||||
|  | ||||
| 	cFILE_OPEN   = 1 | ||||
| 	cFILE_CREATE = 2 | ||||
|  | ||||
| 	cFILE_PIPE_MESSAGE_TYPE          = 1 | ||||
| 	cFILE_PIPE_REJECT_REMOTE_CLIENTS = 2 | ||||
|  | ||||
| 	cSE_DACL_PRESENT = 4 | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| 	// ErrPipeListenerClosed is returned for pipe operations on listeners that have been closed. | ||||
| 	// This error should match net.errClosing since docker takes a dependency on its text. | ||||
| 	ErrPipeListenerClosed = errors.New("use of closed network connection") | ||||
| 	ErrPipeListenerClosed = net.ErrClosed | ||||
|  | ||||
| 	errPipeWriteClosed = errors.New("pipe has been closed for write") | ||||
| ) | ||||
| @@ -116,9 +96,10 @@ func (f *win32Pipe) RemoteAddr() net.Addr { | ||||
| } | ||||
|  | ||||
| func (f *win32Pipe) SetDeadline(t time.Time) error { | ||||
| 	f.SetReadDeadline(t) | ||||
| 	f.SetWriteDeadline(t) | ||||
| 	return nil | ||||
| 	if err := f.SetReadDeadline(t); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return f.SetWriteDeadline(t) | ||||
| } | ||||
|  | ||||
| // CloseWrite closes the write side of a message pipe in byte mode. | ||||
| @@ -157,14 +138,14 @@ func (f *win32MessageBytePipe) Read(b []byte) (int, error) { | ||||
| 		return 0, io.EOF | ||||
| 	} | ||||
| 	n, err := f.win32File.Read(b) | ||||
| 	if err == io.EOF { | ||||
| 	if err == io.EOF { //nolint:errorlint | ||||
| 		// If this was the result of a zero-byte read, then | ||||
| 		// it is possible that the read was due to a zero-size | ||||
| 		// message. Since we are simulating CloseWrite with a | ||||
| 		// zero-byte message, ensure that all future Read() calls | ||||
| 		// also return EOF. | ||||
| 		f.readEOF = true | ||||
| 	} else if err == syscall.ERROR_MORE_DATA { | ||||
| 	} else if err == syscall.ERROR_MORE_DATA { //nolint:errorlint // err is Errno | ||||
| 		// ERROR_MORE_DATA indicates that the pipe's read mode is message mode | ||||
| 		// and the message still has more bytes. Treat this as a success, since | ||||
| 		// this package presents all named pipes as byte streams. | ||||
| @@ -173,7 +154,7 @@ func (f *win32MessageBytePipe) Read(b []byte) (int, error) { | ||||
| 	return n, err | ||||
| } | ||||
|  | ||||
| func (s pipeAddress) Network() string { | ||||
| func (pipeAddress) Network() string { | ||||
| 	return "pipe" | ||||
| } | ||||
|  | ||||
| @@ -184,16 +165,21 @@ func (s pipeAddress) String() string { | ||||
| // tryDialPipe attempts to dial the pipe at `path` until `ctx` cancellation or timeout. | ||||
| func tryDialPipe(ctx context.Context, path *string, access uint32) (syscall.Handle, error) { | ||||
| 	for { | ||||
|  | ||||
| 		select { | ||||
| 		case <-ctx.Done(): | ||||
| 			return syscall.Handle(0), ctx.Err() | ||||
| 		default: | ||||
| 			h, err := createFile(*path, access, 0, nil, syscall.OPEN_EXISTING, syscall.FILE_FLAG_OVERLAPPED|cSECURITY_SQOS_PRESENT|cSECURITY_ANONYMOUS, 0) | ||||
| 			h, err := createFile(*path, | ||||
| 				access, | ||||
| 				0, | ||||
| 				nil, | ||||
| 				syscall.OPEN_EXISTING, | ||||
| 				windows.FILE_FLAG_OVERLAPPED|windows.SECURITY_SQOS_PRESENT|windows.SECURITY_ANONYMOUS, | ||||
| 				0) | ||||
| 			if err == nil { | ||||
| 				return h, nil | ||||
| 			} | ||||
| 			if err != cERROR_PIPE_BUSY { | ||||
| 			if err != windows.ERROR_PIPE_BUSY { //nolint:errorlint // err is Errno | ||||
| 				return h, &os.PathError{Err: err, Op: "open", Path: *path} | ||||
| 			} | ||||
| 			// Wait 10 msec and try again. This is a rather simplistic | ||||
| @@ -213,9 +199,10 @@ func DialPipe(path string, timeout *time.Duration) (net.Conn, error) { | ||||
| 	} else { | ||||
| 		absTimeout = time.Now().Add(2 * time.Second) | ||||
| 	} | ||||
| 	ctx, _ := context.WithDeadline(context.Background(), absTimeout) | ||||
| 	ctx, cancel := context.WithDeadline(context.Background(), absTimeout) | ||||
| 	defer cancel() | ||||
| 	conn, err := DialPipeContext(ctx, path) | ||||
| 	if err == context.DeadlineExceeded { | ||||
| 	if errors.Is(err, context.DeadlineExceeded) { | ||||
| 		return nil, ErrTimeout | ||||
| 	} | ||||
| 	return conn, err | ||||
| @@ -251,7 +238,7 @@ func DialPipeAccess(ctx context.Context, path string, access uint32) (net.Conn, | ||||
|  | ||||
| 	// If the pipe is in message mode, return a message byte pipe, which | ||||
| 	// supports CloseWrite(). | ||||
| 	if flags&cPIPE_TYPE_MESSAGE != 0 { | ||||
| 	if flags&windows.PIPE_TYPE_MESSAGE != 0 { | ||||
| 		return &win32MessageBytePipe{ | ||||
| 			win32Pipe: win32Pipe{win32File: f, path: path}, | ||||
| 		}, nil | ||||
| @@ -283,7 +270,11 @@ func makeServerPipeHandle(path string, sd []byte, c *PipeConfig, first bool) (sy | ||||
| 	oa.Length = unsafe.Sizeof(oa) | ||||
|  | ||||
| 	var ntPath unicodeString | ||||
| 	if err := rtlDosPathNameToNtPathName(&path16[0], &ntPath, 0, 0).Err(); err != nil { | ||||
| 	if err := rtlDosPathNameToNtPathName(&path16[0], | ||||
| 		&ntPath, | ||||
| 		0, | ||||
| 		0, | ||||
| 	).Err(); err != nil { | ||||
| 		return 0, &os.PathError{Op: "open", Path: path, Err: err} | ||||
| 	} | ||||
| 	defer localFree(ntPath.Buffer) | ||||
| @@ -292,8 +283,8 @@ func makeServerPipeHandle(path string, sd []byte, c *PipeConfig, first bool) (sy | ||||
| 	// The security descriptor is only needed for the first pipe. | ||||
| 	if first { | ||||
| 		if sd != nil { | ||||
| 			len := uint32(len(sd)) | ||||
| 			sdb := localAlloc(0, len) | ||||
| 			l := uint32(len(sd)) | ||||
| 			sdb := localAlloc(0, l) | ||||
| 			defer localFree(sdb) | ||||
| 			copy((*[0xffff]byte)(unsafe.Pointer(sdb))[:], sd) | ||||
| 			oa.SecurityDescriptor = (*securityDescriptor)(unsafe.Pointer(sdb)) | ||||
| @@ -301,28 +292,28 @@ func makeServerPipeHandle(path string, sd []byte, c *PipeConfig, first bool) (sy | ||||
| 			// Construct the default named pipe security descriptor. | ||||
| 			var dacl uintptr | ||||
| 			if err := rtlDefaultNpAcl(&dacl).Err(); err != nil { | ||||
| 				return 0, fmt.Errorf("getting default named pipe ACL: %s", err) | ||||
| 				return 0, fmt.Errorf("getting default named pipe ACL: %w", err) | ||||
| 			} | ||||
| 			defer localFree(dacl) | ||||
|  | ||||
| 			sdb := &securityDescriptor{ | ||||
| 				Revision: 1, | ||||
| 				Control:  cSE_DACL_PRESENT, | ||||
| 				Control:  windows.SE_DACL_PRESENT, | ||||
| 				Dacl:     dacl, | ||||
| 			} | ||||
| 			oa.SecurityDescriptor = sdb | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	typ := uint32(cFILE_PIPE_REJECT_REMOTE_CLIENTS) | ||||
| 	typ := uint32(windows.FILE_PIPE_REJECT_REMOTE_CLIENTS) | ||||
| 	if c.MessageMode { | ||||
| 		typ |= cFILE_PIPE_MESSAGE_TYPE | ||||
| 		typ |= windows.FILE_PIPE_MESSAGE_TYPE | ||||
| 	} | ||||
|  | ||||
| 	disposition := uint32(cFILE_OPEN) | ||||
| 	disposition := uint32(windows.FILE_OPEN) | ||||
| 	access := uint32(syscall.GENERIC_READ | syscall.GENERIC_WRITE | syscall.SYNCHRONIZE) | ||||
| 	if first { | ||||
| 		disposition = cFILE_CREATE | ||||
| 		disposition = windows.FILE_CREATE | ||||
| 		// By not asking for read or write access, the named pipe file system | ||||
| 		// will put this pipe into an initially disconnected state, blocking | ||||
| 		// client connections until the next call with first == false. | ||||
| @@ -335,7 +326,20 @@ func makeServerPipeHandle(path string, sd []byte, c *PipeConfig, first bool) (sy | ||||
| 		h    syscall.Handle | ||||
| 		iosb ioStatusBlock | ||||
| 	) | ||||
| 	err = ntCreateNamedPipeFile(&h, access, &oa, &iosb, syscall.FILE_SHARE_READ|syscall.FILE_SHARE_WRITE, disposition, 0, typ, 0, 0, 0xffffffff, uint32(c.InputBufferSize), uint32(c.OutputBufferSize), &timeout).Err() | ||||
| 	err = ntCreateNamedPipeFile(&h, | ||||
| 		access, | ||||
| 		&oa, | ||||
| 		&iosb, | ||||
| 		syscall.FILE_SHARE_READ|syscall.FILE_SHARE_WRITE, | ||||
| 		disposition, | ||||
| 		0, | ||||
| 		typ, | ||||
| 		0, | ||||
| 		0, | ||||
| 		0xffffffff, | ||||
| 		uint32(c.InputBufferSize), | ||||
| 		uint32(c.OutputBufferSize), | ||||
| 		&timeout).Err() | ||||
| 	if err != nil { | ||||
| 		return 0, &os.PathError{Op: "open", Path: path, Err: err} | ||||
| 	} | ||||
| @@ -380,7 +384,7 @@ func (l *win32PipeListener) makeConnectedServerPipe() (*win32File, error) { | ||||
| 		p.Close() | ||||
| 		p = nil | ||||
| 		err = <-ch | ||||
| 		if err == nil || err == ErrFileClosed { | ||||
| 		if err == nil || err == ErrFileClosed { //nolint:errorlint // err is Errno | ||||
| 			err = ErrPipeListenerClosed | ||||
| 		} | ||||
| 	} | ||||
| @@ -402,12 +406,12 @@ func (l *win32PipeListener) listenerRoutine() { | ||||
| 				p, err = l.makeConnectedServerPipe() | ||||
| 				// If the connection was immediately closed by the client, try | ||||
| 				// again. | ||||
| 				if err != cERROR_NO_DATA { | ||||
| 				if err != windows.ERROR_NO_DATA { //nolint:errorlint // err is Errno | ||||
| 					break | ||||
| 				} | ||||
| 			} | ||||
| 			responseCh <- acceptResponse{p, err} | ||||
| 			closed = err == ErrPipeListenerClosed | ||||
| 			closed = err == ErrPipeListenerClosed //nolint:errorlint // err is Errno | ||||
| 		} | ||||
| 	} | ||||
| 	syscall.Close(l.firstHandle) | ||||
| @@ -469,15 +473,15 @@ func ListenPipe(path string, c *PipeConfig) (net.Listener, error) { | ||||
| } | ||||
|  | ||||
| func connectPipe(p *win32File) error { | ||||
| 	c, err := p.prepareIo() | ||||
| 	c, err := p.prepareIO() | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	defer p.wg.Done() | ||||
|  | ||||
| 	err = connectNamedPipe(p.handle, &c.o) | ||||
| 	_, err = p.asyncIo(c, nil, 0, err) | ||||
| 	if err != nil && err != cERROR_PIPE_CONNECTED { | ||||
| 	_, err = p.asyncIO(c, nil, 0, err) | ||||
| 	if err != nil && err != windows.ERROR_PIPE_CONNECTED { //nolint:errorlint // err is Errno | ||||
| 		return err | ||||
| 	} | ||||
| 	return nil | ||||
|   | ||||
							
								
								
									
										25
									
								
								vendor/github.com/Microsoft/go-winio/pkg/guid/guid.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										25
									
								
								vendor/github.com/Microsoft/go-winio/pkg/guid/guid.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,5 +1,3 @@ | ||||
| // +build windows | ||||
|  | ||||
| // Package guid provides a GUID type. The backing structure for a GUID is | ||||
| // identical to that used by the golang.org/x/sys/windows GUID type. | ||||
| // There are two main binary encodings used for a GUID, the big-endian encoding, | ||||
| @@ -9,26 +7,26 @@ package guid | ||||
|  | ||||
| import ( | ||||
| 	"crypto/rand" | ||||
| 	"crypto/sha1" | ||||
| 	"crypto/sha1" //nolint:gosec // not used for secure application | ||||
| 	"encoding" | ||||
| 	"encoding/binary" | ||||
| 	"fmt" | ||||
| 	"strconv" | ||||
|  | ||||
| 	"golang.org/x/sys/windows" | ||||
| ) | ||||
|  | ||||
| //go:generate go run golang.org/x/tools/cmd/stringer -type=Variant -trimprefix=Variant -linecomment | ||||
|  | ||||
| // Variant specifies which GUID variant (or "type") of the GUID. It determines | ||||
| // how the entirety of the rest of the GUID is interpreted. | ||||
| type Variant uint8 | ||||
|  | ||||
| // The variants specified by RFC 4122. | ||||
| // The variants specified by RFC 4122 section 4.1.1. | ||||
| const ( | ||||
| 	// VariantUnknown specifies a GUID variant which does not conform to one of | ||||
| 	// the variant encodings specified in RFC 4122. | ||||
| 	VariantUnknown Variant = iota | ||||
| 	VariantNCS | ||||
| 	VariantRFC4122 | ||||
| 	VariantRFC4122 // RFC 4122 | ||||
| 	VariantMicrosoft | ||||
| 	VariantFuture | ||||
| ) | ||||
| @@ -38,16 +36,13 @@ const ( | ||||
| // hash of an input string. | ||||
| type Version uint8 | ||||
|  | ||||
| func (v Version) String() string { | ||||
| 	return strconv.FormatUint(uint64(v), 10) | ||||
| } | ||||
|  | ||||
| var _ = (encoding.TextMarshaler)(GUID{}) | ||||
| var _ = (encoding.TextUnmarshaler)(&GUID{}) | ||||
|  | ||||
| // GUID represents a GUID/UUID. It has the same structure as | ||||
| // golang.org/x/sys/windows.GUID so that it can be used with functions expecting | ||||
| // that type. It is defined as its own type so that stringification and | ||||
| // marshaling can be supported. The representation matches that used by native | ||||
| // Windows code. | ||||
| type GUID windows.GUID | ||||
|  | ||||
| // NewV4 returns a new version 4 (pseudorandom) GUID, as defined by RFC 4122. | ||||
| func NewV4() (GUID, error) { | ||||
| 	var b [16]byte | ||||
| @@ -70,7 +65,7 @@ func NewV4() (GUID, error) { | ||||
| // big-endian UTF16 stream of bytes. If that is desired, the string can be | ||||
| // encoded as such before being passed to this function. | ||||
| func NewV5(namespace GUID, name []byte) (GUID, error) { | ||||
| 	b := sha1.New() | ||||
| 	b := sha1.New() //nolint:gosec // not used for secure application | ||||
| 	namespaceBytes := namespace.ToArray() | ||||
| 	b.Write(namespaceBytes[:]) | ||||
| 	b.Write(name) | ||||
|   | ||||
							
								
								
									
										16
									
								
								vendor/github.com/Microsoft/go-winio/pkg/guid/guid_nonwindows.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								vendor/github.com/Microsoft/go-winio/pkg/guid/guid_nonwindows.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,16 @@ | ||||
| //go:build !windows | ||||
| // +build !windows | ||||
|  | ||||
| package guid | ||||
|  | ||||
| // GUID represents a GUID/UUID. It has the same structure as | ||||
| // golang.org/x/sys/windows.GUID so that it can be used with functions expecting | ||||
| // that type. It is defined as its own type as that is only available to builds | ||||
| // targeted at `windows`. The representation matches that used by native Windows | ||||
| // code. | ||||
| type GUID struct { | ||||
| 	Data1 uint32 | ||||
| 	Data2 uint16 | ||||
| 	Data3 uint16 | ||||
| 	Data4 [8]byte | ||||
| } | ||||
							
								
								
									
										13
									
								
								vendor/github.com/Microsoft/go-winio/pkg/guid/guid_windows.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								vendor/github.com/Microsoft/go-winio/pkg/guid/guid_windows.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | ||||
| //go:build windows | ||||
| // +build windows | ||||
|  | ||||
| package guid | ||||
|  | ||||
| import "golang.org/x/sys/windows" | ||||
|  | ||||
| // GUID represents a GUID/UUID. It has the same structure as | ||||
| // golang.org/x/sys/windows.GUID so that it can be used with functions expecting | ||||
| // that type. It is defined as its own type so that stringification and | ||||
| // marshaling can be supported. The representation matches that used by native | ||||
| // Windows code. | ||||
| type GUID windows.GUID | ||||
							
								
								
									
										27
									
								
								vendor/github.com/Microsoft/go-winio/pkg/guid/variant_string.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								vendor/github.com/Microsoft/go-winio/pkg/guid/variant_string.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,27 @@ | ||||
| // Code generated by "stringer -type=Variant -trimprefix=Variant -linecomment"; DO NOT EDIT. | ||||
|  | ||||
| package guid | ||||
|  | ||||
| import "strconv" | ||||
|  | ||||
| func _() { | ||||
| 	// An "invalid array index" compiler error signifies that the constant values have changed. | ||||
| 	// Re-run the stringer command to generate them again. | ||||
| 	var x [1]struct{} | ||||
| 	_ = x[VariantUnknown-0] | ||||
| 	_ = x[VariantNCS-1] | ||||
| 	_ = x[VariantRFC4122-2] | ||||
| 	_ = x[VariantMicrosoft-3] | ||||
| 	_ = x[VariantFuture-4] | ||||
| } | ||||
|  | ||||
| const _Variant_name = "UnknownNCSRFC 4122MicrosoftFuture" | ||||
|  | ||||
| var _Variant_index = [...]uint8{0, 7, 10, 18, 27, 33} | ||||
|  | ||||
| func (i Variant) String() string { | ||||
| 	if i >= Variant(len(_Variant_index)-1) { | ||||
| 		return "Variant(" + strconv.FormatInt(int64(i), 10) + ")" | ||||
| 	} | ||||
| 	return _Variant_name[_Variant_index[i]:_Variant_index[i+1]] | ||||
| } | ||||
							
								
								
									
										44
									
								
								vendor/github.com/Microsoft/go-winio/pkg/security/grantvmgroupaccess.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										44
									
								
								vendor/github.com/Microsoft/go-winio/pkg/security/grantvmgroupaccess.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,13 +1,13 @@ | ||||
| //go:build windows | ||||
| // +build windows | ||||
|  | ||||
| package security | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"os" | ||||
| 	"syscall" | ||||
| 	"unsafe" | ||||
|  | ||||
| 	"github.com/pkg/errors" | ||||
| ) | ||||
|  | ||||
| type ( | ||||
| @@ -21,6 +21,7 @@ type ( | ||||
| 	trusteeForm         uint32 | ||||
| 	trusteeType         uint32 | ||||
|  | ||||
| 	//nolint:structcheck // structcheck thinks fields are unused, but the are used to pass data to OS | ||||
| 	explicitAccess struct { | ||||
| 		accessPermissions accessMask | ||||
| 		accessMode        accessMode | ||||
| @@ -28,6 +29,7 @@ type ( | ||||
| 		trustee           trustee | ||||
| 	} | ||||
|  | ||||
| 	//nolint:structcheck,unused // structcheck thinks fields are unused, but the are used to pass data to OS | ||||
| 	trustee struct { | ||||
| 		multipleTrustee          *trustee | ||||
| 		multipleTrusteeOperation int32 | ||||
| @@ -45,6 +47,7 @@ const ( | ||||
| 	desiredAccessReadControl desiredAccess = 0x20000 | ||||
| 	desiredAccessWriteDac    desiredAccess = 0x40000 | ||||
|  | ||||
| 	//cspell:disable-next-line | ||||
| 	gvmga = "GrantVmGroupAccess:" | ||||
|  | ||||
| 	inheritModeNoInheritance                  inheritMode = 0x0 | ||||
| @@ -57,9 +60,9 @@ const ( | ||||
| 	shareModeRead  shareMode = 0x1 | ||||
| 	shareModeWrite shareMode = 0x2 | ||||
|  | ||||
| 	sidVmGroup = "S-1-5-83-0" | ||||
| 	sidVMGroup = "S-1-5-83-0" | ||||
|  | ||||
| 	trusteeFormIsSid trusteeForm = 0 | ||||
| 	trusteeFormIsSID trusteeForm = 0 | ||||
|  | ||||
| 	trusteeTypeWellKnownGroup trusteeType = 5 | ||||
| ) | ||||
| @@ -68,11 +71,13 @@ const ( | ||||
| // include Grant ACE entries for the VM Group SID. This is a golang re- | ||||
| // implementation of the same function in vmcompute, just not exported in | ||||
| // RS5. Which kind of sucks. Sucks a lot :/ | ||||
| // | ||||
| //revive:disable-next-line:var-naming VM, not Vm | ||||
| func GrantVmGroupAccess(name string) error { | ||||
| 	// Stat (to determine if `name` is a directory). | ||||
| 	s, err := os.Stat(name) | ||||
| 	if err != nil { | ||||
| 		return errors.Wrapf(err, "%s os.Stat %s", gvmga, name) | ||||
| 		return fmt.Errorf("%s os.Stat %s: %w", gvmga, name, err) | ||||
| 	} | ||||
|  | ||||
| 	// Get a handle to the file/directory. Must defer Close on success. | ||||
| @@ -80,7 +85,7 @@ func GrantVmGroupAccess(name string) error { | ||||
| 	if err != nil { | ||||
| 		return err // Already wrapped | ||||
| 	} | ||||
| 	defer syscall.CloseHandle(fd) | ||||
| 	defer syscall.CloseHandle(fd) //nolint:errcheck | ||||
|  | ||||
| 	// Get the current DACL and Security Descriptor. Must defer LocalFree on success. | ||||
| 	ot := objectTypeFileObject | ||||
| @@ -88,9 +93,9 @@ func GrantVmGroupAccess(name string) error { | ||||
| 	sd := uintptr(0) | ||||
| 	origDACL := uintptr(0) | ||||
| 	if err := getSecurityInfo(fd, uint32(ot), uint32(si), nil, nil, &origDACL, nil, &sd); err != nil { | ||||
| 		return errors.Wrapf(err, "%s GetSecurityInfo %s", gvmga, name) | ||||
| 		return fmt.Errorf("%s GetSecurityInfo %s: %w", gvmga, name, err) | ||||
| 	} | ||||
| 	defer syscall.LocalFree((syscall.Handle)(unsafe.Pointer(sd))) | ||||
| 	defer syscall.LocalFree((syscall.Handle)(unsafe.Pointer(sd))) //nolint:errcheck | ||||
|  | ||||
| 	// Generate a new DACL which is the current DACL with the required ACEs added. | ||||
| 	// Must defer LocalFree on success. | ||||
| @@ -98,11 +103,11 @@ func GrantVmGroupAccess(name string) error { | ||||
| 	if err != nil { | ||||
| 		return err // Already wrapped | ||||
| 	} | ||||
| 	defer syscall.LocalFree((syscall.Handle)(unsafe.Pointer(newDACL))) | ||||
| 	defer syscall.LocalFree((syscall.Handle)(unsafe.Pointer(newDACL))) //nolint:errcheck | ||||
|  | ||||
| 	// And finally use SetSecurityInfo to apply the updated DACL. | ||||
| 	if err := setSecurityInfo(fd, uint32(ot), uint32(si), uintptr(0), uintptr(0), newDACL, uintptr(0)); err != nil { | ||||
| 		return errors.Wrapf(err, "%s SetSecurityInfo %s", gvmga, name) | ||||
| 		return fmt.Errorf("%s SetSecurityInfo %s: %w", gvmga, name, err) | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| @@ -111,16 +116,19 @@ func GrantVmGroupAccess(name string) error { | ||||
| // createFile is a helper function to call [Nt]CreateFile to get a handle to | ||||
| // the file or directory. | ||||
| func createFile(name string, isDir bool) (syscall.Handle, error) { | ||||
| 	namep := syscall.StringToUTF16(name) | ||||
| 	namep, err := syscall.UTF16FromString(name) | ||||
| 	if err != nil { | ||||
| 		return syscall.InvalidHandle, fmt.Errorf("could not convernt name to UTF-16: %w", err) | ||||
| 	} | ||||
| 	da := uint32(desiredAccessReadControl | desiredAccessWriteDac) | ||||
| 	sm := uint32(shareModeRead | shareModeWrite) | ||||
| 	fa := uint32(syscall.FILE_ATTRIBUTE_NORMAL) | ||||
| 	if isDir { | ||||
| 		fa = uint32(fa | syscall.FILE_FLAG_BACKUP_SEMANTICS) | ||||
| 		fa |= syscall.FILE_FLAG_BACKUP_SEMANTICS | ||||
| 	} | ||||
| 	fd, err := syscall.CreateFile(&namep[0], da, sm, nil, syscall.OPEN_EXISTING, fa, 0) | ||||
| 	if err != nil { | ||||
| 		return 0, errors.Wrapf(err, "%s syscall.CreateFile %s", gvmga, name) | ||||
| 		return syscall.InvalidHandle, fmt.Errorf("%s syscall.CreateFile %s: %w", gvmga, name, err) | ||||
| 	} | ||||
| 	return fd, nil | ||||
| } | ||||
| @@ -129,9 +137,9 @@ func createFile(name string, isDir bool) (syscall.Handle, error) { | ||||
| // The caller is responsible for LocalFree of the returned DACL on success. | ||||
| func generateDACLWithAcesAdded(name string, isDir bool, origDACL uintptr) (uintptr, error) { | ||||
| 	// Generate pointers to the SIDs based on the string SIDs | ||||
| 	sid, err := syscall.StringToSid(sidVmGroup) | ||||
| 	sid, err := syscall.StringToSid(sidVMGroup) | ||||
| 	if err != nil { | ||||
| 		return 0, errors.Wrapf(err, "%s syscall.StringToSid %s %s", gvmga, name, sidVmGroup) | ||||
| 		return 0, fmt.Errorf("%s syscall.StringToSid %s %s: %w", gvmga, name, sidVMGroup, err) | ||||
| 	} | ||||
|  | ||||
| 	inheritance := inheritModeNoInheritance | ||||
| @@ -140,12 +148,12 @@ func generateDACLWithAcesAdded(name string, isDir bool, origDACL uintptr) (uintp | ||||
| 	} | ||||
|  | ||||
| 	eaArray := []explicitAccess{ | ||||
| 		explicitAccess{ | ||||
| 		{ | ||||
| 			accessPermissions: accessMaskDesiredPermission, | ||||
| 			accessMode:        accessModeGrant, | ||||
| 			inheritance:       inheritance, | ||||
| 			trustee: trustee{ | ||||
| 				trusteeForm: trusteeFormIsSid, | ||||
| 				trusteeForm: trusteeFormIsSID, | ||||
| 				trusteeType: trusteeTypeWellKnownGroup, | ||||
| 				name:        uintptr(unsafe.Pointer(sid)), | ||||
| 			}, | ||||
| @@ -154,7 +162,7 @@ func generateDACLWithAcesAdded(name string, isDir bool, origDACL uintptr) (uintp | ||||
|  | ||||
| 	modifiedDACL := uintptr(0) | ||||
| 	if err := setEntriesInAcl(uintptr(uint32(1)), uintptr(unsafe.Pointer(&eaArray[0])), origDACL, &modifiedDACL); err != nil { | ||||
| 		return 0, errors.Wrapf(err, "%s SetEntriesInAcl %s", gvmga, name) | ||||
| 		return 0, fmt.Errorf("%s SetEntriesInAcl %s: %w", gvmga, name, err) | ||||
| 	} | ||||
|  | ||||
| 	return modifiedDACL, nil | ||||
|   | ||||
							
								
								
									
										8
									
								
								vendor/github.com/Microsoft/go-winio/pkg/security/syscall_windows.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										8
									
								
								vendor/github.com/Microsoft/go-winio/pkg/security/syscall_windows.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,7 +1,7 @@ | ||||
| package security | ||||
|  | ||||
| //go:generate go run mksyscall_windows.go -output zsyscall_windows.go syscall_windows.go | ||||
| //go:generate go run github.com/Microsoft/go-winio/tools/mkwinsyscall -output zsyscall_windows.go syscall_windows.go | ||||
|  | ||||
| //sys getSecurityInfo(handle syscall.Handle, objectType uint32, si uint32, ppsidOwner **uintptr, ppsidGroup **uintptr, ppDacl *uintptr, ppSacl *uintptr, ppSecurityDescriptor *uintptr) (err error) [failretval!=0] = advapi32.GetSecurityInfo | ||||
| //sys setSecurityInfo(handle syscall.Handle, objectType uint32, si uint32, psidOwner uintptr, psidGroup uintptr, pDacl uintptr, pSacl uintptr) (err error) [failretval!=0] = advapi32.SetSecurityInfo | ||||
| //sys setEntriesInAcl(count uintptr, pListOfEEs uintptr, oldAcl uintptr, newAcl *uintptr) (err error) [failretval!=0] = advapi32.SetEntriesInAclW | ||||
| //sys getSecurityInfo(handle syscall.Handle, objectType uint32, si uint32, ppsidOwner **uintptr, ppsidGroup **uintptr, ppDacl *uintptr, ppSacl *uintptr, ppSecurityDescriptor *uintptr) (win32err error) = advapi32.GetSecurityInfo | ||||
| //sys setSecurityInfo(handle syscall.Handle, objectType uint32, si uint32, psidOwner uintptr, psidGroup uintptr, pDacl uintptr, pSacl uintptr) (win32err error) = advapi32.SetSecurityInfo | ||||
| //sys setEntriesInAcl(count uintptr, pListOfEEs uintptr, oldAcl uintptr, newAcl *uintptr) (win32err error) = advapi32.SetEntriesInAclW | ||||
|   | ||||
							
								
								
									
										28
									
								
								vendor/github.com/Microsoft/go-winio/pkg/security/zsyscall_windows.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										28
									
								
								vendor/github.com/Microsoft/go-winio/pkg/security/zsyscall_windows.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,4 +1,6 @@ | ||||
| // Code generated by 'go generate'; DO NOT EDIT. | ||||
| //go:build windows | ||||
|  | ||||
| // Code generated by 'go generate' using "github.com/Microsoft/go-winio/tools/mkwinsyscall"; DO NOT EDIT. | ||||
|  | ||||
| package security | ||||
|  | ||||
| @@ -45,26 +47,26 @@ var ( | ||||
| 	procSetSecurityInfo  = modadvapi32.NewProc("SetSecurityInfo") | ||||
| ) | ||||
|  | ||||
| func getSecurityInfo(handle syscall.Handle, objectType uint32, si uint32, ppsidOwner **uintptr, ppsidGroup **uintptr, ppDacl *uintptr, ppSacl *uintptr, ppSecurityDescriptor *uintptr) (err error) { | ||||
| 	r1, _, e1 := syscall.Syscall9(procGetSecurityInfo.Addr(), 8, uintptr(handle), uintptr(objectType), uintptr(si), uintptr(unsafe.Pointer(ppsidOwner)), uintptr(unsafe.Pointer(ppsidGroup)), uintptr(unsafe.Pointer(ppDacl)), uintptr(unsafe.Pointer(ppSacl)), uintptr(unsafe.Pointer(ppSecurityDescriptor)), 0) | ||||
| 	if r1 != 0 { | ||||
| 		err = errnoErr(e1) | ||||
| func getSecurityInfo(handle syscall.Handle, objectType uint32, si uint32, ppsidOwner **uintptr, ppsidGroup **uintptr, ppDacl *uintptr, ppSacl *uintptr, ppSecurityDescriptor *uintptr) (win32err error) { | ||||
| 	r0, _, _ := syscall.Syscall9(procGetSecurityInfo.Addr(), 8, uintptr(handle), uintptr(objectType), uintptr(si), uintptr(unsafe.Pointer(ppsidOwner)), uintptr(unsafe.Pointer(ppsidGroup)), uintptr(unsafe.Pointer(ppDacl)), uintptr(unsafe.Pointer(ppSacl)), uintptr(unsafe.Pointer(ppSecurityDescriptor)), 0) | ||||
| 	if r0 != 0 { | ||||
| 		win32err = syscall.Errno(r0) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
|  | ||||
| func setEntriesInAcl(count uintptr, pListOfEEs uintptr, oldAcl uintptr, newAcl *uintptr) (err error) { | ||||
| 	r1, _, e1 := syscall.Syscall6(procSetEntriesInAclW.Addr(), 4, uintptr(count), uintptr(pListOfEEs), uintptr(oldAcl), uintptr(unsafe.Pointer(newAcl)), 0, 0) | ||||
| 	if r1 != 0 { | ||||
| 		err = errnoErr(e1) | ||||
| func setEntriesInAcl(count uintptr, pListOfEEs uintptr, oldAcl uintptr, newAcl *uintptr) (win32err error) { | ||||
| 	r0, _, _ := syscall.Syscall6(procSetEntriesInAclW.Addr(), 4, uintptr(count), uintptr(pListOfEEs), uintptr(oldAcl), uintptr(unsafe.Pointer(newAcl)), 0, 0) | ||||
| 	if r0 != 0 { | ||||
| 		win32err = syscall.Errno(r0) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
|  | ||||
| func setSecurityInfo(handle syscall.Handle, objectType uint32, si uint32, psidOwner uintptr, psidGroup uintptr, pDacl uintptr, pSacl uintptr) (err error) { | ||||
| 	r1, _, e1 := syscall.Syscall9(procSetSecurityInfo.Addr(), 7, uintptr(handle), uintptr(objectType), uintptr(si), uintptr(psidOwner), uintptr(psidGroup), uintptr(pDacl), uintptr(pSacl), 0, 0) | ||||
| 	if r1 != 0 { | ||||
| 		err = errnoErr(e1) | ||||
| func setSecurityInfo(handle syscall.Handle, objectType uint32, si uint32, psidOwner uintptr, psidGroup uintptr, pDacl uintptr, pSacl uintptr) (win32err error) { | ||||
| 	r0, _, _ := syscall.Syscall9(procSetSecurityInfo.Addr(), 7, uintptr(handle), uintptr(objectType), uintptr(si), uintptr(psidOwner), uintptr(psidGroup), uintptr(pDacl), uintptr(pSacl), 0, 0) | ||||
| 	if r0 != 0 { | ||||
| 		win32err = syscall.Errno(r0) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
|   | ||||
							
								
								
									
										37
									
								
								vendor/github.com/Microsoft/go-winio/privilege.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										37
									
								
								vendor/github.com/Microsoft/go-winio/privilege.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,3 +1,4 @@ | ||||
| //go:build windows | ||||
| // +build windows | ||||
|  | ||||
| package winio | ||||
| @@ -24,19 +25,15 @@ import ( | ||||
| //sys lookupPrivilegeDisplayName(systemName string, name *uint16, buffer *uint16, size *uint32, languageId *uint32) (err error) = advapi32.LookupPrivilegeDisplayNameW | ||||
|  | ||||
| const ( | ||||
| 	SE_PRIVILEGE_ENABLED = 2 | ||||
| 	//revive:disable-next-line:var-naming ALL_CAPS | ||||
| 	SE_PRIVILEGE_ENABLED = windows.SE_PRIVILEGE_ENABLED | ||||
|  | ||||
| 	ERROR_NOT_ALL_ASSIGNED syscall.Errno = 1300 | ||||
| 	//revive:disable-next-line:var-naming ALL_CAPS | ||||
| 	ERROR_NOT_ALL_ASSIGNED syscall.Errno = windows.ERROR_NOT_ALL_ASSIGNED | ||||
|  | ||||
| 	SeBackupPrivilege  = "SeBackupPrivilege" | ||||
| 	SeRestorePrivilege = "SeRestorePrivilege" | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	securityAnonymous = iota | ||||
| 	securityIdentification | ||||
| 	securityImpersonation | ||||
| 	securityDelegation | ||||
| 	SeBackupPrivilege   = "SeBackupPrivilege" | ||||
| 	SeRestorePrivilege  = "SeRestorePrivilege" | ||||
| 	SeSecurityPrivilege = "SeSecurityPrivilege" | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| @@ -50,11 +47,9 @@ type PrivilegeError struct { | ||||
| } | ||||
|  | ||||
| func (e *PrivilegeError) Error() string { | ||||
| 	s := "" | ||||
| 	s := "Could not enable privilege " | ||||
| 	if len(e.privileges) > 1 { | ||||
| 		s = "Could not enable privileges " | ||||
| 	} else { | ||||
| 		s = "Could not enable privilege " | ||||
| 	} | ||||
| 	for i, p := range e.privileges { | ||||
| 		if i != 0 { | ||||
| @@ -93,7 +88,7 @@ func RunWithPrivileges(names []string, fn func() error) error { | ||||
| } | ||||
|  | ||||
| func mapPrivileges(names []string) ([]uint64, error) { | ||||
| 	var privileges []uint64 | ||||
| 	privileges := make([]uint64, 0, len(names)) | ||||
| 	privNameMutex.Lock() | ||||
| 	defer privNameMutex.Unlock() | ||||
| 	for _, name := range names { | ||||
| @@ -126,7 +121,7 @@ func enableDisableProcessPrivilege(names []string, action uint32) error { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	p, _ := windows.GetCurrentProcess() | ||||
| 	p := windows.CurrentProcess() | ||||
| 	var token windows.Token | ||||
| 	err = windows.OpenProcessToken(p, windows.TOKEN_ADJUST_PRIVILEGES|windows.TOKEN_QUERY, &token) | ||||
| 	if err != nil { | ||||
| @@ -139,10 +134,10 @@ func enableDisableProcessPrivilege(names []string, action uint32) error { | ||||
|  | ||||
| func adjustPrivileges(token windows.Token, privileges []uint64, action uint32) error { | ||||
| 	var b bytes.Buffer | ||||
| 	binary.Write(&b, binary.LittleEndian, uint32(len(privileges))) | ||||
| 	_ = binary.Write(&b, binary.LittleEndian, uint32(len(privileges))) | ||||
| 	for _, p := range privileges { | ||||
| 		binary.Write(&b, binary.LittleEndian, p) | ||||
| 		binary.Write(&b, binary.LittleEndian, action) | ||||
| 		_ = binary.Write(&b, binary.LittleEndian, p) | ||||
| 		_ = binary.Write(&b, binary.LittleEndian, action) | ||||
| 	} | ||||
| 	prevState := make([]byte, b.Len()) | ||||
| 	reqSize := uint32(0) | ||||
| @@ -150,7 +145,7 @@ func adjustPrivileges(token windows.Token, privileges []uint64, action uint32) e | ||||
| 	if !success { | ||||
| 		return err | ||||
| 	} | ||||
| 	if err == ERROR_NOT_ALL_ASSIGNED { | ||||
| 	if err == ERROR_NOT_ALL_ASSIGNED { //nolint:errorlint // err is Errno | ||||
| 		return &PrivilegeError{privileges} | ||||
| 	} | ||||
| 	return nil | ||||
| @@ -176,7 +171,7 @@ func getPrivilegeName(luid uint64) string { | ||||
| } | ||||
|  | ||||
| func newThreadToken() (windows.Token, error) { | ||||
| 	err := impersonateSelf(securityImpersonation) | ||||
| 	err := impersonateSelf(windows.SecurityImpersonation) | ||||
| 	if err != nil { | ||||
| 		return 0, err | ||||
| 	} | ||||
|   | ||||
							
								
								
									
										11
									
								
								vendor/github.com/Microsoft/go-winio/reparse.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										11
									
								
								vendor/github.com/Microsoft/go-winio/reparse.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,3 +1,6 @@ | ||||
| //go:build windows | ||||
| // +build windows | ||||
|  | ||||
| package winio | ||||
|  | ||||
| import ( | ||||
| @@ -113,16 +116,16 @@ func EncodeReparsePoint(rp *ReparsePoint) []byte { | ||||
| 	} | ||||
|  | ||||
| 	var b bytes.Buffer | ||||
| 	binary.Write(&b, binary.LittleEndian, &data) | ||||
| 	_ = binary.Write(&b, binary.LittleEndian, &data) | ||||
| 	if !rp.IsMountPoint { | ||||
| 		flags := uint32(0) | ||||
| 		if relative { | ||||
| 			flags |= 1 | ||||
| 		} | ||||
| 		binary.Write(&b, binary.LittleEndian, flags) | ||||
| 		_ = binary.Write(&b, binary.LittleEndian, flags) | ||||
| 	} | ||||
|  | ||||
| 	binary.Write(&b, binary.LittleEndian, ntTarget16) | ||||
| 	binary.Write(&b, binary.LittleEndian, target16) | ||||
| 	_ = binary.Write(&b, binary.LittleEndian, ntTarget16) | ||||
| 	_ = binary.Write(&b, binary.LittleEndian, target16) | ||||
| 	return b.Bytes() | ||||
| } | ||||
|   | ||||
							
								
								
									
										64
									
								
								vendor/github.com/Microsoft/go-winio/sd.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										64
									
								
								vendor/github.com/Microsoft/go-winio/sd.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,23 +1,25 @@ | ||||
| //go:build windows | ||||
| // +build windows | ||||
|  | ||||
| package winio | ||||
|  | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"syscall" | ||||
| 	"unsafe" | ||||
|  | ||||
| 	"golang.org/x/sys/windows" | ||||
| ) | ||||
|  | ||||
| //sys lookupAccountName(systemName *uint16, accountName string, sid *byte, sidSize *uint32, refDomain *uint16, refDomainSize *uint32, sidNameUse *uint32) (err error) = advapi32.LookupAccountNameW | ||||
| //sys lookupAccountSid(systemName *uint16, sid *byte, name *uint16, nameSize *uint32, refDomain *uint16, refDomainSize *uint32, sidNameUse *uint32) (err error) = advapi32.LookupAccountSidW | ||||
| //sys convertSidToStringSid(sid *byte, str **uint16) (err error) = advapi32.ConvertSidToStringSidW | ||||
| //sys convertStringSidToSid(str *uint16, sid **byte) (err error) = advapi32.ConvertStringSidToSidW | ||||
| //sys convertStringSecurityDescriptorToSecurityDescriptor(str string, revision uint32, sd *uintptr, size *uint32) (err error) = advapi32.ConvertStringSecurityDescriptorToSecurityDescriptorW | ||||
| //sys convertSecurityDescriptorToStringSecurityDescriptor(sd *byte, revision uint32, secInfo uint32, sddl **uint16, sddlSize *uint32) (err error) = advapi32.ConvertSecurityDescriptorToStringSecurityDescriptorW | ||||
| //sys localFree(mem uintptr) = LocalFree | ||||
| //sys getSecurityDescriptorLength(sd uintptr) (len uint32) = advapi32.GetSecurityDescriptorLength | ||||
|  | ||||
| const ( | ||||
| 	cERROR_NONE_MAPPED = syscall.Errno(1332) | ||||
| ) | ||||
|  | ||||
| type AccountLookupError struct { | ||||
| 	Name string | ||||
| 	Err  error | ||||
| @@ -28,8 +30,10 @@ func (e *AccountLookupError) Error() string { | ||||
| 		return "lookup account: empty account name specified" | ||||
| 	} | ||||
| 	var s string | ||||
| 	switch e.Err { | ||||
| 	case cERROR_NONE_MAPPED: | ||||
| 	switch { | ||||
| 	case errors.Is(e.Err, windows.ERROR_INVALID_SID): | ||||
| 		s = "the security ID structure is invalid" | ||||
| 	case errors.Is(e.Err, windows.ERROR_NONE_MAPPED): | ||||
| 		s = "not found" | ||||
| 	default: | ||||
| 		s = e.Err.Error() | ||||
| @@ -37,6 +41,8 @@ func (e *AccountLookupError) Error() string { | ||||
| 	return "lookup account " + e.Name + ": " + s | ||||
| } | ||||
|  | ||||
| func (e *AccountLookupError) Unwrap() error { return e.Err } | ||||
|  | ||||
| type SddlConversionError struct { | ||||
| 	Sddl string | ||||
| 	Err  error | ||||
| @@ -46,15 +52,19 @@ func (e *SddlConversionError) Error() string { | ||||
| 	return "convert " + e.Sddl + ": " + e.Err.Error() | ||||
| } | ||||
|  | ||||
| func (e *SddlConversionError) Unwrap() error { return e.Err } | ||||
|  | ||||
| // LookupSidByName looks up the SID of an account by name | ||||
| // | ||||
| //revive:disable-next-line:var-naming SID, not Sid | ||||
| func LookupSidByName(name string) (sid string, err error) { | ||||
| 	if name == "" { | ||||
| 		return "", &AccountLookupError{name, cERROR_NONE_MAPPED} | ||||
| 		return "", &AccountLookupError{name, windows.ERROR_NONE_MAPPED} | ||||
| 	} | ||||
|  | ||||
| 	var sidSize, sidNameUse, refDomainSize uint32 | ||||
| 	err = lookupAccountName(nil, name, nil, &sidSize, nil, &refDomainSize, &sidNameUse) | ||||
| 	if err != nil && err != syscall.ERROR_INSUFFICIENT_BUFFER { | ||||
| 	if err != nil && err != syscall.ERROR_INSUFFICIENT_BUFFER { //nolint:errorlint // err is Errno | ||||
| 		return "", &AccountLookupError{name, err} | ||||
| 	} | ||||
| 	sidBuffer := make([]byte, sidSize) | ||||
| @@ -73,6 +83,42 @@ func LookupSidByName(name string) (sid string, err error) { | ||||
| 	return sid, nil | ||||
| } | ||||
|  | ||||
| // LookupNameBySid looks up the name of an account by SID | ||||
| // | ||||
| //revive:disable-next-line:var-naming SID, not Sid | ||||
| func LookupNameBySid(sid string) (name string, err error) { | ||||
| 	if sid == "" { | ||||
| 		return "", &AccountLookupError{sid, windows.ERROR_NONE_MAPPED} | ||||
| 	} | ||||
|  | ||||
| 	sidBuffer, err := windows.UTF16PtrFromString(sid) | ||||
| 	if err != nil { | ||||
| 		return "", &AccountLookupError{sid, err} | ||||
| 	} | ||||
|  | ||||
| 	var sidPtr *byte | ||||
| 	if err = convertStringSidToSid(sidBuffer, &sidPtr); err != nil { | ||||
| 		return "", &AccountLookupError{sid, err} | ||||
| 	} | ||||
| 	defer localFree(uintptr(unsafe.Pointer(sidPtr))) | ||||
|  | ||||
| 	var nameSize, refDomainSize, sidNameUse uint32 | ||||
| 	err = lookupAccountSid(nil, sidPtr, nil, &nameSize, nil, &refDomainSize, &sidNameUse) | ||||
| 	if err != nil && err != windows.ERROR_INSUFFICIENT_BUFFER { //nolint:errorlint // err is Errno | ||||
| 		return "", &AccountLookupError{sid, err} | ||||
| 	} | ||||
|  | ||||
| 	nameBuffer := make([]uint16, nameSize) | ||||
| 	refDomainBuffer := make([]uint16, refDomainSize) | ||||
| 	err = lookupAccountSid(nil, sidPtr, &nameBuffer[0], &nameSize, &refDomainBuffer[0], &refDomainSize, &sidNameUse) | ||||
| 	if err != nil { | ||||
| 		return "", &AccountLookupError{sid, err} | ||||
| 	} | ||||
|  | ||||
| 	name = windows.UTF16ToString(nameBuffer) | ||||
| 	return name, nil | ||||
| } | ||||
|  | ||||
| func SddlToSecurityDescriptor(sddl string) ([]byte, error) { | ||||
| 	var sdBuffer uintptr | ||||
| 	err := convertStringSecurityDescriptorToSecurityDescriptor(sddl, 1, &sdBuffer, nil) | ||||
| @@ -87,7 +133,7 @@ func SddlToSecurityDescriptor(sddl string) ([]byte, error) { | ||||
|  | ||||
| func SecurityDescriptorToSddl(sd []byte) (string, error) { | ||||
| 	var sddl *uint16 | ||||
| 	// The returned string length seems to including an aribtrary number of terminating NULs. | ||||
| 	// The returned string length seems to include an arbitrary number of terminating NULs. | ||||
| 	// Don't use it. | ||||
| 	err := convertSecurityDescriptorToStringSecurityDescriptor(&sd[0], 1, 0xff, &sddl, nil) | ||||
| 	if err != nil { | ||||
|   | ||||
							
								
								
									
										4
									
								
								vendor/github.com/Microsoft/go-winio/syscall.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								vendor/github.com/Microsoft/go-winio/syscall.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,3 +1,5 @@ | ||||
| //go:build windows | ||||
|  | ||||
| package winio | ||||
|  | ||||
| //go:generate go run golang.org/x/sys/windows/mkwinsyscall -output zsyscall_windows.go file.go pipe.go sd.go fileinfo.go privilege.go backup.go hvsock.go | ||||
| //go:generate go run github.com/Microsoft/go-winio/tools/mkwinsyscall -output zsyscall_windows.go ./*.go | ||||
|   | ||||
							
								
								
									
										5
									
								
								vendor/github.com/Microsoft/go-winio/tools.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								vendor/github.com/Microsoft/go-winio/tools.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | ||||
| //go:build tools | ||||
|  | ||||
| package winio | ||||
|  | ||||
| import _ "golang.org/x/tools/cmd/stringer" | ||||
							
								
								
									
										122
									
								
								vendor/github.com/Microsoft/go-winio/vhd/vhd.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										122
									
								
								vendor/github.com/Microsoft/go-winio/vhd/vhd.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,3 +1,4 @@ | ||||
| //go:build windows | ||||
| // +build windows | ||||
|  | ||||
| package vhd | ||||
| @@ -7,17 +8,16 @@ import ( | ||||
| 	"syscall" | ||||
|  | ||||
| 	"github.com/Microsoft/go-winio/pkg/guid" | ||||
| 	"github.com/pkg/errors" | ||||
| 	"golang.org/x/sys/windows" | ||||
| ) | ||||
|  | ||||
| //go:generate go run mksyscall_windows.go -output zvhd_windows.go vhd.go | ||||
| //go:generate go run github.com/Microsoft/go-winio/tools/mkwinsyscall -output zvhd_windows.go vhd.go | ||||
|  | ||||
| //sys createVirtualDisk(virtualStorageType *VirtualStorageType, path string, virtualDiskAccessMask uint32, securityDescriptor *uintptr, createVirtualDiskFlags uint32, providerSpecificFlags uint32, parameters *CreateVirtualDiskParameters, overlapped *syscall.Overlapped, handle *syscall.Handle) (err error) [failretval != 0] = virtdisk.CreateVirtualDisk | ||||
| //sys openVirtualDisk(virtualStorageType *VirtualStorageType, path string, virtualDiskAccessMask uint32, openVirtualDiskFlags uint32, parameters *OpenVirtualDiskParameters, handle *syscall.Handle) (err error) [failretval != 0] = virtdisk.OpenVirtualDisk | ||||
| //sys attachVirtualDisk(handle syscall.Handle, securityDescriptor *uintptr, attachVirtualDiskFlag uint32, providerSpecificFlags uint32, parameters *AttachVirtualDiskParameters, overlapped *syscall.Overlapped) (err error) [failretval != 0] = virtdisk.AttachVirtualDisk | ||||
| //sys detachVirtualDisk(handle syscall.Handle, detachVirtualDiskFlags uint32, providerSpecificFlags uint32) (err error) [failretval != 0] = virtdisk.DetachVirtualDisk | ||||
| //sys getVirtualDiskPhysicalPath(handle syscall.Handle, diskPathSizeInBytes *uint32, buffer *uint16) (err error) [failretval != 0] = virtdisk.GetVirtualDiskPhysicalPath | ||||
| //sys createVirtualDisk(virtualStorageType *VirtualStorageType, path string, virtualDiskAccessMask uint32, securityDescriptor *uintptr, createVirtualDiskFlags uint32, providerSpecificFlags uint32, parameters *CreateVirtualDiskParameters, overlapped *syscall.Overlapped, handle *syscall.Handle) (win32err error) = virtdisk.CreateVirtualDisk | ||||
| //sys openVirtualDisk(virtualStorageType *VirtualStorageType, path string, virtualDiskAccessMask uint32, openVirtualDiskFlags uint32, parameters *openVirtualDiskParameters, handle *syscall.Handle) (win32err error) = virtdisk.OpenVirtualDisk | ||||
| //sys attachVirtualDisk(handle syscall.Handle, securityDescriptor *uintptr, attachVirtualDiskFlag uint32, providerSpecificFlags uint32, parameters *AttachVirtualDiskParameters, overlapped *syscall.Overlapped) (win32err error) = virtdisk.AttachVirtualDisk | ||||
| //sys detachVirtualDisk(handle syscall.Handle, detachVirtualDiskFlags uint32, providerSpecificFlags uint32) (win32err error) = virtdisk.DetachVirtualDisk | ||||
| //sys getVirtualDiskPhysicalPath(handle syscall.Handle, diskPathSizeInBytes *uint32, buffer *uint16) (win32err error) = virtdisk.GetVirtualDiskPhysicalPath | ||||
|  | ||||
| type ( | ||||
| 	CreateVirtualDiskFlag uint32 | ||||
| @@ -62,20 +62,35 @@ type OpenVirtualDiskParameters struct { | ||||
| 	Version2 OpenVersion2 | ||||
| } | ||||
|  | ||||
| // The higher level `OpenVersion2` struct uses `bool`s to refer to `GetInfoOnly` and `ReadOnly` for ease of use. However, | ||||
| // the internal windows structure uses `BOOL`s aka int32s for these types. `openVersion2` is used for translating | ||||
| // `OpenVersion2` fields to the correct windows internal field types on the `Open____` methods. | ||||
| type openVersion2 struct { | ||||
| 	getInfoOnly    int32 | ||||
| 	readOnly       int32 | ||||
| 	resiliencyGUID guid.GUID | ||||
| } | ||||
|  | ||||
| type openVirtualDiskParameters struct { | ||||
| 	version  uint32 | ||||
| 	version2 openVersion2 | ||||
| } | ||||
|  | ||||
| type AttachVersion2 struct { | ||||
| 	RestrictedOffset uint64 | ||||
| 	RestrictedLength uint64 | ||||
| } | ||||
|  | ||||
| type AttachVirtualDiskParameters struct { | ||||
| 	Version  uint32 // Must always be set to 2 | ||||
| 	Version  uint32 | ||||
| 	Version2 AttachVersion2 | ||||
| } | ||||
|  | ||||
| const ( | ||||
| 	//revive:disable-next-line:var-naming ALL_CAPS | ||||
| 	VIRTUAL_STORAGE_TYPE_DEVICE_VHDX = 0x3 | ||||
|  | ||||
| 	// Access Mask for opening a VHD | ||||
| 	// Access Mask for opening a VHD. | ||||
| 	VirtualDiskAccessNone     VirtualDiskAccessMask = 0x00000000 | ||||
| 	VirtualDiskAccessAttachRO VirtualDiskAccessMask = 0x00010000 | ||||
| 	VirtualDiskAccessAttachRW VirtualDiskAccessMask = 0x00020000 | ||||
| @@ -87,7 +102,7 @@ const ( | ||||
| 	VirtualDiskAccessAll      VirtualDiskAccessMask = 0x003f0000 | ||||
| 	VirtualDiskAccessWritable VirtualDiskAccessMask = 0x00320000 | ||||
|  | ||||
| 	// Flags for creating a VHD | ||||
| 	// Flags for creating a VHD. | ||||
| 	CreateVirtualDiskFlagNone                              CreateVirtualDiskFlag = 0x0 | ||||
| 	CreateVirtualDiskFlagFullPhysicalAllocation            CreateVirtualDiskFlag = 0x1 | ||||
| 	CreateVirtualDiskFlagPreventWritesToSourceDisk         CreateVirtualDiskFlag = 0x2 | ||||
| @@ -95,12 +110,12 @@ const ( | ||||
| 	CreateVirtualDiskFlagCreateBackingStorage              CreateVirtualDiskFlag = 0x8 | ||||
| 	CreateVirtualDiskFlagUseChangeTrackingSourceLimit      CreateVirtualDiskFlag = 0x10 | ||||
| 	CreateVirtualDiskFlagPreserveParentChangeTrackingState CreateVirtualDiskFlag = 0x20 | ||||
| 	CreateVirtualDiskFlagVhdSetUseOriginalBackingStorage   CreateVirtualDiskFlag = 0x40 | ||||
| 	CreateVirtualDiskFlagVhdSetUseOriginalBackingStorage   CreateVirtualDiskFlag = 0x40 //revive:disable-line:var-naming VHD, not Vhd | ||||
| 	CreateVirtualDiskFlagSparseFile                        CreateVirtualDiskFlag = 0x80 | ||||
| 	CreateVirtualDiskFlagPmemCompatible                    CreateVirtualDiskFlag = 0x100 | ||||
| 	CreateVirtualDiskFlagPmemCompatible                    CreateVirtualDiskFlag = 0x100 //revive:disable-line:var-naming PMEM, not Pmem | ||||
| 	CreateVirtualDiskFlagSupportCompressedVolumes          CreateVirtualDiskFlag = 0x200 | ||||
|  | ||||
| 	// Flags for opening a VHD | ||||
| 	// Flags for opening a VHD. | ||||
| 	OpenVirtualDiskFlagNone                        VirtualDiskFlag = 0x00000000 | ||||
| 	OpenVirtualDiskFlagNoParents                   VirtualDiskFlag = 0x00000001 | ||||
| 	OpenVirtualDiskFlagBlankFile                   VirtualDiskFlag = 0x00000002 | ||||
| @@ -113,7 +128,7 @@ const ( | ||||
| 	OpenVirtualDiskFlagNoWriteHardening            VirtualDiskFlag = 0x00000100 | ||||
| 	OpenVirtualDiskFlagSupportCompressedVolumes    VirtualDiskFlag = 0x00000200 | ||||
|  | ||||
| 	// Flags for attaching a VHD | ||||
| 	// Flags for attaching a VHD. | ||||
| 	AttachVirtualDiskFlagNone                          AttachVirtualDiskFlag = 0x00000000 | ||||
| 	AttachVirtualDiskFlagReadOnly                      AttachVirtualDiskFlag = 0x00000001 | ||||
| 	AttachVirtualDiskFlagNoDriveLetter                 AttachVirtualDiskFlag = 0x00000002 | ||||
| @@ -126,12 +141,14 @@ const ( | ||||
| 	AttachVirtualDiskFlagSinglePartition               AttachVirtualDiskFlag = 0x00000100 | ||||
| 	AttachVirtualDiskFlagRegisterVolume                AttachVirtualDiskFlag = 0x00000200 | ||||
|  | ||||
| 	// Flags for detaching a VHD | ||||
| 	// Flags for detaching a VHD. | ||||
| 	DetachVirtualDiskFlagNone DetachVirtualDiskFlag = 0x0 | ||||
| ) | ||||
|  | ||||
| // CreateVhdx is a helper function to create a simple vhdx file at the given path using | ||||
| // default values. | ||||
| // | ||||
| //revive:disable-next-line:var-naming VHDX, not Vhdx | ||||
| func CreateVhdx(path string, maxSizeInGb, blockSizeInMb uint32) error { | ||||
| 	params := CreateVirtualDiskParameters{ | ||||
| 		Version: 2, | ||||
| @@ -146,21 +163,20 @@ func CreateVhdx(path string, maxSizeInGb, blockSizeInMb uint32) error { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	if err := syscall.CloseHandle(handle); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return nil | ||||
| 	return syscall.CloseHandle(handle) | ||||
| } | ||||
|  | ||||
| // DetachVirtualDisk detaches a virtual hard disk by handle. | ||||
| func DetachVirtualDisk(handle syscall.Handle) (err error) { | ||||
| 	if err := detachVirtualDisk(handle, 0, 0); err != nil { | ||||
| 		return errors.Wrap(err, "failed to detach virtual disk") | ||||
| 		return fmt.Errorf("failed to detach virtual disk: %w", err) | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // DetachVhd detaches a vhd found at `path`. | ||||
| // | ||||
| //revive:disable-next-line:var-naming VHD, not Vhd | ||||
| func DetachVhd(path string) error { | ||||
| 	handle, err := OpenVirtualDisk( | ||||
| 		path, | ||||
| @@ -170,12 +186,16 @@ func DetachVhd(path string) error { | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	defer syscall.CloseHandle(handle) | ||||
| 	defer syscall.CloseHandle(handle) //nolint:errcheck | ||||
| 	return DetachVirtualDisk(handle) | ||||
| } | ||||
|  | ||||
| // AttachVirtualDisk attaches a virtual hard disk for use. | ||||
| func AttachVirtualDisk(handle syscall.Handle, attachVirtualDiskFlag AttachVirtualDiskFlag, parameters *AttachVirtualDiskParameters) (err error) { | ||||
| func AttachVirtualDisk( | ||||
| 	handle syscall.Handle, | ||||
| 	attachVirtualDiskFlag AttachVirtualDiskFlag, | ||||
| 	parameters *AttachVirtualDiskParameters, | ||||
| ) (err error) { | ||||
| 	// Supports both version 1 and 2 of the attach parameters as version 2 wasn't present in RS5. | ||||
| 	if err := attachVirtualDisk( | ||||
| 		handle, | ||||
| @@ -185,13 +205,15 @@ func AttachVirtualDisk(handle syscall.Handle, attachVirtualDiskFlag AttachVirtua | ||||
| 		parameters, | ||||
| 		nil, | ||||
| 	); err != nil { | ||||
| 		return errors.Wrap(err, "failed to attach virtual disk") | ||||
| 		return fmt.Errorf("failed to attach virtual disk: %w", err) | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // AttachVhd attaches a virtual hard disk at `path` for use. Attaches using version 2 | ||||
| // of the ATTACH_VIRTUAL_DISK_PARAMETERS. | ||||
| // | ||||
| //revive:disable-next-line:var-naming VHD, not Vhd | ||||
| func AttachVhd(path string) (err error) { | ||||
| 	handle, err := OpenVirtualDisk( | ||||
| 		path, | ||||
| @@ -202,20 +224,24 @@ func AttachVhd(path string) (err error) { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	defer syscall.CloseHandle(handle) | ||||
| 	defer syscall.CloseHandle(handle) //nolint:errcheck | ||||
| 	params := AttachVirtualDiskParameters{Version: 2} | ||||
| 	if err := AttachVirtualDisk( | ||||
| 		handle, | ||||
| 		AttachVirtualDiskFlagNone, | ||||
| 		¶ms, | ||||
| 	); err != nil { | ||||
| 		return errors.Wrap(err, "failed to attach virtual disk") | ||||
| 		return fmt.Errorf("failed to attach virtual disk: %w", err) | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // OpenVirtualDisk obtains a handle to a VHD opened with supplied access mask and flags. | ||||
| func OpenVirtualDisk(vhdPath string, virtualDiskAccessMask VirtualDiskAccessMask, openVirtualDiskFlags VirtualDiskFlag) (syscall.Handle, error) { | ||||
| func OpenVirtualDisk( | ||||
| 	vhdPath string, | ||||
| 	virtualDiskAccessMask VirtualDiskAccessMask, | ||||
| 	openVirtualDiskFlags VirtualDiskFlag, | ||||
| ) (syscall.Handle, error) { | ||||
| 	parameters := OpenVirtualDiskParameters{Version: 2} | ||||
| 	handle, err := OpenVirtualDiskWithParameters( | ||||
| 		vhdPath, | ||||
| @@ -230,29 +256,55 @@ func OpenVirtualDisk(vhdPath string, virtualDiskAccessMask VirtualDiskAccessMask | ||||
| } | ||||
|  | ||||
| // OpenVirtualDiskWithParameters obtains a handle to a VHD opened with supplied access mask, flags and parameters. | ||||
| func OpenVirtualDiskWithParameters(vhdPath string, virtualDiskAccessMask VirtualDiskAccessMask, openVirtualDiskFlags VirtualDiskFlag, parameters *OpenVirtualDiskParameters) (syscall.Handle, error) { | ||||
| func OpenVirtualDiskWithParameters( | ||||
| 	vhdPath string, | ||||
| 	virtualDiskAccessMask VirtualDiskAccessMask, | ||||
| 	openVirtualDiskFlags VirtualDiskFlag, | ||||
| 	parameters *OpenVirtualDiskParameters, | ||||
| ) (syscall.Handle, error) { | ||||
| 	var ( | ||||
| 		handle      syscall.Handle | ||||
| 		defaultType VirtualStorageType | ||||
| 		getInfoOnly int32 | ||||
| 		readOnly    int32 | ||||
| 	) | ||||
| 	if parameters.Version != 2 { | ||||
| 		return handle, fmt.Errorf("only version 2 VHDs are supported, found version: %d", parameters.Version) | ||||
| 	} | ||||
| 	if parameters.Version2.GetInfoOnly { | ||||
| 		getInfoOnly = 1 | ||||
| 	} | ||||
| 	if parameters.Version2.ReadOnly { | ||||
| 		readOnly = 1 | ||||
| 	} | ||||
| 	params := &openVirtualDiskParameters{ | ||||
| 		version: parameters.Version, | ||||
| 		version2: openVersion2{ | ||||
| 			getInfoOnly, | ||||
| 			readOnly, | ||||
| 			parameters.Version2.ResiliencyGUID, | ||||
| 		}, | ||||
| 	} | ||||
| 	if err := openVirtualDisk( | ||||
| 		&defaultType, | ||||
| 		vhdPath, | ||||
| 		uint32(virtualDiskAccessMask), | ||||
| 		uint32(openVirtualDiskFlags), | ||||
| 		parameters, | ||||
| 		params, | ||||
| 		&handle, | ||||
| 	); err != nil { | ||||
| 		return 0, errors.Wrap(err, "failed to open virtual disk") | ||||
| 		return 0, fmt.Errorf("failed to open virtual disk: %w", err) | ||||
| 	} | ||||
| 	return handle, nil | ||||
| } | ||||
|  | ||||
| // CreateVirtualDisk creates a virtual harddisk and returns a handle to the disk. | ||||
| func CreateVirtualDisk(path string, virtualDiskAccessMask VirtualDiskAccessMask, createVirtualDiskFlags CreateVirtualDiskFlag, parameters *CreateVirtualDiskParameters) (syscall.Handle, error) { | ||||
| func CreateVirtualDisk( | ||||
| 	path string, | ||||
| 	virtualDiskAccessMask VirtualDiskAccessMask, | ||||
| 	createVirtualDiskFlags CreateVirtualDiskFlag, | ||||
| 	parameters *CreateVirtualDiskParameters, | ||||
| ) (syscall.Handle, error) { | ||||
| 	var ( | ||||
| 		handle      syscall.Handle | ||||
| 		defaultType VirtualStorageType | ||||
| @@ -272,7 +324,7 @@ func CreateVirtualDisk(path string, virtualDiskAccessMask VirtualDiskAccessMask, | ||||
| 		nil, | ||||
| 		&handle, | ||||
| 	); err != nil { | ||||
| 		return handle, errors.Wrap(err, "failed to create virtual disk") | ||||
| 		return handle, fmt.Errorf("failed to create virtual disk: %w", err) | ||||
| 	} | ||||
| 	return handle, nil | ||||
| } | ||||
| @@ -290,12 +342,14 @@ func GetVirtualDiskPhysicalPath(handle syscall.Handle) (_ string, err error) { | ||||
| 		&diskPathSizeInBytes, | ||||
| 		&diskPhysicalPathBuf[0], | ||||
| 	); err != nil { | ||||
| 		return "", errors.Wrap(err, "failed to get disk physical path") | ||||
| 		return "", fmt.Errorf("failed to get disk physical path: %w", err) | ||||
| 	} | ||||
| 	return windows.UTF16ToString(diskPhysicalPathBuf[:]), nil | ||||
| } | ||||
|  | ||||
| // CreateDiffVhd is a helper function to create a differencing virtual disk. | ||||
| // | ||||
| //revive:disable-next-line:var-naming VHD, not Vhd | ||||
| func CreateDiffVhd(diffVhdPath, baseVhdPath string, blockSizeInMB uint32) error { | ||||
| 	// Setting `ParentPath` is how to signal to create a differencing disk. | ||||
| 	createParams := &CreateVirtualDiskParameters{ | ||||
| @@ -314,10 +368,10 @@ func CreateDiffVhd(diffVhdPath, baseVhdPath string, blockSizeInMB uint32) error | ||||
| 		createParams, | ||||
| 	) | ||||
| 	if err != nil { | ||||
| 		return fmt.Errorf("failed to create differencing vhd: %s", err) | ||||
| 		return fmt.Errorf("failed to create differencing vhd: %w", err) | ||||
| 	} | ||||
| 	if err := syscall.CloseHandle(vhdHandle); err != nil { | ||||
| 		return fmt.Errorf("failed to close differencing vhd handle: %s", err) | ||||
| 		return fmt.Errorf("failed to close differencing vhd handle: %w", err) | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|   | ||||
							
								
								
									
										56
									
								
								vendor/github.com/Microsoft/go-winio/vhd/zvhd_windows.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										56
									
								
								vendor/github.com/Microsoft/go-winio/vhd/zvhd_windows.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,4 +1,6 @@ | ||||
| // Code generated by 'go generate'; DO NOT EDIT. | ||||
| //go:build windows | ||||
|  | ||||
| // Code generated by 'go generate' using "github.com/Microsoft/go-winio/tools/mkwinsyscall"; DO NOT EDIT. | ||||
|  | ||||
| package vhd | ||||
|  | ||||
| @@ -47,60 +49,60 @@ var ( | ||||
| 	procOpenVirtualDisk            = modvirtdisk.NewProc("OpenVirtualDisk") | ||||
| ) | ||||
|  | ||||
| func attachVirtualDisk(handle syscall.Handle, securityDescriptor *uintptr, attachVirtualDiskFlag uint32, providerSpecificFlags uint32, parameters *AttachVirtualDiskParameters, overlapped *syscall.Overlapped) (err error) { | ||||
| 	r1, _, e1 := syscall.Syscall6(procAttachVirtualDisk.Addr(), 6, uintptr(handle), uintptr(unsafe.Pointer(securityDescriptor)), uintptr(attachVirtualDiskFlag), uintptr(providerSpecificFlags), uintptr(unsafe.Pointer(parameters)), uintptr(unsafe.Pointer(overlapped))) | ||||
| 	if r1 != 0 { | ||||
| 		err = errnoErr(e1) | ||||
| func attachVirtualDisk(handle syscall.Handle, securityDescriptor *uintptr, attachVirtualDiskFlag uint32, providerSpecificFlags uint32, parameters *AttachVirtualDiskParameters, overlapped *syscall.Overlapped) (win32err error) { | ||||
| 	r0, _, _ := syscall.Syscall6(procAttachVirtualDisk.Addr(), 6, uintptr(handle), uintptr(unsafe.Pointer(securityDescriptor)), uintptr(attachVirtualDiskFlag), uintptr(providerSpecificFlags), uintptr(unsafe.Pointer(parameters)), uintptr(unsafe.Pointer(overlapped))) | ||||
| 	if r0 != 0 { | ||||
| 		win32err = syscall.Errno(r0) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
|  | ||||
| func createVirtualDisk(virtualStorageType *VirtualStorageType, path string, virtualDiskAccessMask uint32, securityDescriptor *uintptr, createVirtualDiskFlags uint32, providerSpecificFlags uint32, parameters *CreateVirtualDiskParameters, overlapped *syscall.Overlapped, handle *syscall.Handle) (err error) { | ||||
| func createVirtualDisk(virtualStorageType *VirtualStorageType, path string, virtualDiskAccessMask uint32, securityDescriptor *uintptr, createVirtualDiskFlags uint32, providerSpecificFlags uint32, parameters *CreateVirtualDiskParameters, overlapped *syscall.Overlapped, handle *syscall.Handle) (win32err error) { | ||||
| 	var _p0 *uint16 | ||||
| 	_p0, err = syscall.UTF16PtrFromString(path) | ||||
| 	if err != nil { | ||||
| 	_p0, win32err = syscall.UTF16PtrFromString(path) | ||||
| 	if win32err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	return _createVirtualDisk(virtualStorageType, _p0, virtualDiskAccessMask, securityDescriptor, createVirtualDiskFlags, providerSpecificFlags, parameters, overlapped, handle) | ||||
| } | ||||
|  | ||||
| func _createVirtualDisk(virtualStorageType *VirtualStorageType, path *uint16, virtualDiskAccessMask uint32, securityDescriptor *uintptr, createVirtualDiskFlags uint32, providerSpecificFlags uint32, parameters *CreateVirtualDiskParameters, overlapped *syscall.Overlapped, handle *syscall.Handle) (err error) { | ||||
| 	r1, _, e1 := syscall.Syscall9(procCreateVirtualDisk.Addr(), 9, uintptr(unsafe.Pointer(virtualStorageType)), uintptr(unsafe.Pointer(path)), uintptr(virtualDiskAccessMask), uintptr(unsafe.Pointer(securityDescriptor)), uintptr(createVirtualDiskFlags), uintptr(providerSpecificFlags), uintptr(unsafe.Pointer(parameters)), uintptr(unsafe.Pointer(overlapped)), uintptr(unsafe.Pointer(handle))) | ||||
| 	if r1 != 0 { | ||||
| 		err = errnoErr(e1) | ||||
| func _createVirtualDisk(virtualStorageType *VirtualStorageType, path *uint16, virtualDiskAccessMask uint32, securityDescriptor *uintptr, createVirtualDiskFlags uint32, providerSpecificFlags uint32, parameters *CreateVirtualDiskParameters, overlapped *syscall.Overlapped, handle *syscall.Handle) (win32err error) { | ||||
| 	r0, _, _ := syscall.Syscall9(procCreateVirtualDisk.Addr(), 9, uintptr(unsafe.Pointer(virtualStorageType)), uintptr(unsafe.Pointer(path)), uintptr(virtualDiskAccessMask), uintptr(unsafe.Pointer(securityDescriptor)), uintptr(createVirtualDiskFlags), uintptr(providerSpecificFlags), uintptr(unsafe.Pointer(parameters)), uintptr(unsafe.Pointer(overlapped)), uintptr(unsafe.Pointer(handle))) | ||||
| 	if r0 != 0 { | ||||
| 		win32err = syscall.Errno(r0) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
|  | ||||
| func detachVirtualDisk(handle syscall.Handle, detachVirtualDiskFlags uint32, providerSpecificFlags uint32) (err error) { | ||||
| 	r1, _, e1 := syscall.Syscall(procDetachVirtualDisk.Addr(), 3, uintptr(handle), uintptr(detachVirtualDiskFlags), uintptr(providerSpecificFlags)) | ||||
| 	if r1 != 0 { | ||||
| 		err = errnoErr(e1) | ||||
| func detachVirtualDisk(handle syscall.Handle, detachVirtualDiskFlags uint32, providerSpecificFlags uint32) (win32err error) { | ||||
| 	r0, _, _ := syscall.Syscall(procDetachVirtualDisk.Addr(), 3, uintptr(handle), uintptr(detachVirtualDiskFlags), uintptr(providerSpecificFlags)) | ||||
| 	if r0 != 0 { | ||||
| 		win32err = syscall.Errno(r0) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
|  | ||||
| func getVirtualDiskPhysicalPath(handle syscall.Handle, diskPathSizeInBytes *uint32, buffer *uint16) (err error) { | ||||
| 	r1, _, e1 := syscall.Syscall(procGetVirtualDiskPhysicalPath.Addr(), 3, uintptr(handle), uintptr(unsafe.Pointer(diskPathSizeInBytes)), uintptr(unsafe.Pointer(buffer))) | ||||
| 	if r1 != 0 { | ||||
| 		err = errnoErr(e1) | ||||
| func getVirtualDiskPhysicalPath(handle syscall.Handle, diskPathSizeInBytes *uint32, buffer *uint16) (win32err error) { | ||||
| 	r0, _, _ := syscall.Syscall(procGetVirtualDiskPhysicalPath.Addr(), 3, uintptr(handle), uintptr(unsafe.Pointer(diskPathSizeInBytes)), uintptr(unsafe.Pointer(buffer))) | ||||
| 	if r0 != 0 { | ||||
| 		win32err = syscall.Errno(r0) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
|  | ||||
| func openVirtualDisk(virtualStorageType *VirtualStorageType, path string, virtualDiskAccessMask uint32, openVirtualDiskFlags uint32, parameters *OpenVirtualDiskParameters, handle *syscall.Handle) (err error) { | ||||
| func openVirtualDisk(virtualStorageType *VirtualStorageType, path string, virtualDiskAccessMask uint32, openVirtualDiskFlags uint32, parameters *openVirtualDiskParameters, handle *syscall.Handle) (win32err error) { | ||||
| 	var _p0 *uint16 | ||||
| 	_p0, err = syscall.UTF16PtrFromString(path) | ||||
| 	if err != nil { | ||||
| 	_p0, win32err = syscall.UTF16PtrFromString(path) | ||||
| 	if win32err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	return _openVirtualDisk(virtualStorageType, _p0, virtualDiskAccessMask, openVirtualDiskFlags, parameters, handle) | ||||
| } | ||||
|  | ||||
| func _openVirtualDisk(virtualStorageType *VirtualStorageType, path *uint16, virtualDiskAccessMask uint32, openVirtualDiskFlags uint32, parameters *OpenVirtualDiskParameters, handle *syscall.Handle) (err error) { | ||||
| 	r1, _, e1 := syscall.Syscall6(procOpenVirtualDisk.Addr(), 6, uintptr(unsafe.Pointer(virtualStorageType)), uintptr(unsafe.Pointer(path)), uintptr(virtualDiskAccessMask), uintptr(openVirtualDiskFlags), uintptr(unsafe.Pointer(parameters)), uintptr(unsafe.Pointer(handle))) | ||||
| 	if r1 != 0 { | ||||
| 		err = errnoErr(e1) | ||||
| func _openVirtualDisk(virtualStorageType *VirtualStorageType, path *uint16, virtualDiskAccessMask uint32, openVirtualDiskFlags uint32, parameters *openVirtualDiskParameters, handle *syscall.Handle) (win32err error) { | ||||
| 	r0, _, _ := syscall.Syscall6(procOpenVirtualDisk.Addr(), 6, uintptr(unsafe.Pointer(virtualStorageType)), uintptr(unsafe.Pointer(path)), uintptr(virtualDiskAccessMask), uintptr(openVirtualDiskFlags), uintptr(unsafe.Pointer(parameters)), uintptr(unsafe.Pointer(handle))) | ||||
| 	if r0 != 0 { | ||||
| 		win32err = syscall.Errno(r0) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
|   | ||||
							
								
								
									
										45
									
								
								vendor/github.com/Microsoft/go-winio/zsyscall_windows.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										45
									
								
								vendor/github.com/Microsoft/go-winio/zsyscall_windows.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,4 +1,6 @@ | ||||
| // Code generated by 'go generate'; DO NOT EDIT. | ||||
| //go:build windows | ||||
|  | ||||
| // Code generated by 'go generate' using "github.com/Microsoft/go-winio/tools/mkwinsyscall"; DO NOT EDIT. | ||||
|  | ||||
| package winio | ||||
|  | ||||
| @@ -47,9 +49,11 @@ var ( | ||||
| 	procConvertSecurityDescriptorToStringSecurityDescriptorW = modadvapi32.NewProc("ConvertSecurityDescriptorToStringSecurityDescriptorW") | ||||
| 	procConvertSidToStringSidW                               = modadvapi32.NewProc("ConvertSidToStringSidW") | ||||
| 	procConvertStringSecurityDescriptorToSecurityDescriptorW = modadvapi32.NewProc("ConvertStringSecurityDescriptorToSecurityDescriptorW") | ||||
| 	procConvertStringSidToSidW                               = modadvapi32.NewProc("ConvertStringSidToSidW") | ||||
| 	procGetSecurityDescriptorLength                          = modadvapi32.NewProc("GetSecurityDescriptorLength") | ||||
| 	procImpersonateSelf                                      = modadvapi32.NewProc("ImpersonateSelf") | ||||
| 	procLookupAccountNameW                                   = modadvapi32.NewProc("LookupAccountNameW") | ||||
| 	procLookupAccountSidW                                    = modadvapi32.NewProc("LookupAccountSidW") | ||||
| 	procLookupPrivilegeDisplayNameW                          = modadvapi32.NewProc("LookupPrivilegeDisplayNameW") | ||||
| 	procLookupPrivilegeNameW                                 = modadvapi32.NewProc("LookupPrivilegeNameW") | ||||
| 	procLookupPrivilegeValueW                                = modadvapi32.NewProc("LookupPrivilegeValueW") | ||||
| @@ -74,7 +78,6 @@ var ( | ||||
| 	procRtlDosPathNameToNtPathName_U                         = modntdll.NewProc("RtlDosPathNameToNtPathName_U") | ||||
| 	procRtlNtStatusToDosErrorNoTeb                           = modntdll.NewProc("RtlNtStatusToDosErrorNoTeb") | ||||
| 	procWSAGetOverlappedResult                               = modws2_32.NewProc("WSAGetOverlappedResult") | ||||
| 	procbind                                                 = modws2_32.NewProc("bind") | ||||
| ) | ||||
|  | ||||
| func adjustTokenPrivileges(token windows.Token, releaseAll bool, input *byte, outputSize uint32, output *byte, requiredSize *uint32) (success bool, err error) { | ||||
| @@ -123,6 +126,14 @@ func _convertStringSecurityDescriptorToSecurityDescriptor(str *uint16, revision | ||||
| 	return | ||||
| } | ||||
|  | ||||
| func convertStringSidToSid(str *uint16, sid **byte) (err error) { | ||||
| 	r1, _, e1 := syscall.Syscall(procConvertStringSidToSidW.Addr(), 2, uintptr(unsafe.Pointer(str)), uintptr(unsafe.Pointer(sid)), 0) | ||||
| 	if r1 == 0 { | ||||
| 		err = errnoErr(e1) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
|  | ||||
| func getSecurityDescriptorLength(sd uintptr) (len uint32) { | ||||
| 	r0, _, _ := syscall.Syscall(procGetSecurityDescriptorLength.Addr(), 1, uintptr(sd), 0, 0) | ||||
| 	len = uint32(r0) | ||||
| @@ -154,6 +165,14 @@ func _lookupAccountName(systemName *uint16, accountName *uint16, sid *byte, sidS | ||||
| 	return | ||||
| } | ||||
|  | ||||
| func lookupAccountSid(systemName *uint16, sid *byte, name *uint16, nameSize *uint32, refDomain *uint16, refDomainSize *uint32, sidNameUse *uint32) (err error) { | ||||
| 	r1, _, e1 := syscall.Syscall9(procLookupAccountSidW.Addr(), 7, uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(sid)), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(nameSize)), uintptr(unsafe.Pointer(refDomain)), uintptr(unsafe.Pointer(refDomainSize)), uintptr(unsafe.Pointer(sidNameUse)), 0, 0) | ||||
| 	if r1 == 0 { | ||||
| 		err = errnoErr(e1) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
|  | ||||
| func lookupPrivilegeDisplayName(systemName string, name *uint16, buffer *uint16, size *uint32, languageId *uint32) (err error) { | ||||
| 	var _p0 *uint16 | ||||
| 	_p0, err = syscall.UTF16PtrFromString(systemName) | ||||
| @@ -380,25 +399,25 @@ func setFileCompletionNotificationModes(h syscall.Handle, flags uint8) (err erro | ||||
| 	return | ||||
| } | ||||
|  | ||||
| func ntCreateNamedPipeFile(pipe *syscall.Handle, access uint32, oa *objectAttributes, iosb *ioStatusBlock, share uint32, disposition uint32, options uint32, typ uint32, readMode uint32, completionMode uint32, maxInstances uint32, inboundQuota uint32, outputQuota uint32, timeout *int64) (status ntstatus) { | ||||
| func ntCreateNamedPipeFile(pipe *syscall.Handle, access uint32, oa *objectAttributes, iosb *ioStatusBlock, share uint32, disposition uint32, options uint32, typ uint32, readMode uint32, completionMode uint32, maxInstances uint32, inboundQuota uint32, outputQuota uint32, timeout *int64) (status ntStatus) { | ||||
| 	r0, _, _ := syscall.Syscall15(procNtCreateNamedPipeFile.Addr(), 14, uintptr(unsafe.Pointer(pipe)), uintptr(access), uintptr(unsafe.Pointer(oa)), uintptr(unsafe.Pointer(iosb)), uintptr(share), uintptr(disposition), uintptr(options), uintptr(typ), uintptr(readMode), uintptr(completionMode), uintptr(maxInstances), uintptr(inboundQuota), uintptr(outputQuota), uintptr(unsafe.Pointer(timeout)), 0) | ||||
| 	status = ntstatus(r0) | ||||
| 	status = ntStatus(r0) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| func rtlDefaultNpAcl(dacl *uintptr) (status ntstatus) { | ||||
| func rtlDefaultNpAcl(dacl *uintptr) (status ntStatus) { | ||||
| 	r0, _, _ := syscall.Syscall(procRtlDefaultNpAcl.Addr(), 1, uintptr(unsafe.Pointer(dacl)), 0, 0) | ||||
| 	status = ntstatus(r0) | ||||
| 	status = ntStatus(r0) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| func rtlDosPathNameToNtPathName(name *uint16, ntName *unicodeString, filePart uintptr, reserved uintptr) (status ntstatus) { | ||||
| func rtlDosPathNameToNtPathName(name *uint16, ntName *unicodeString, filePart uintptr, reserved uintptr) (status ntStatus) { | ||||
| 	r0, _, _ := syscall.Syscall6(procRtlDosPathNameToNtPathName_U.Addr(), 4, uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(ntName)), uintptr(filePart), uintptr(reserved), 0, 0) | ||||
| 	status = ntstatus(r0) | ||||
| 	status = ntStatus(r0) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| func rtlNtStatusToDosError(status ntstatus) (winerr error) { | ||||
| func rtlNtStatusToDosError(status ntStatus) (winerr error) { | ||||
| 	r0, _, _ := syscall.Syscall(procRtlNtStatusToDosErrorNoTeb.Addr(), 1, uintptr(status), 0, 0) | ||||
| 	if r0 != 0 { | ||||
| 		winerr = syscall.Errno(r0) | ||||
| @@ -417,11 +436,3 @@ func wsaGetOverlappedResult(h syscall.Handle, o *syscall.Overlapped, bytes *uint | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
|  | ||||
| func bind(s syscall.Handle, name unsafe.Pointer, namelen int32) (err error) { | ||||
| 	r1, _, e1 := syscall.Syscall(procbind.Addr(), 3, uintptr(s), uintptr(name), uintptr(namelen)) | ||||
| 	if r1 == socketError { | ||||
| 		err = errnoErr(e1) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
|   | ||||
							
								
								
									
										657
									
								
								vendor/golang.org/x/tools/cmd/stringer/stringer.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										657
									
								
								vendor/golang.org/x/tools/cmd/stringer/stringer.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,657 @@ | ||||
| // Copyright 2014 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. | ||||
|  | ||||
| // Stringer is a tool to automate the creation of methods that satisfy the fmt.Stringer | ||||
| // interface. Given the name of a (signed or unsigned) integer type T that has constants | ||||
| // defined, stringer will create a new self-contained Go source file implementing | ||||
| // | ||||
| //	func (t T) String() string | ||||
| // | ||||
| // The file is created in the same package and directory as the package that defines T. | ||||
| // It has helpful defaults designed for use with go generate. | ||||
| // | ||||
| // Stringer works best with constants that are consecutive values such as created using iota, | ||||
| // but creates good code regardless. In the future it might also provide custom support for | ||||
| // constant sets that are bit patterns. | ||||
| // | ||||
| // For example, given this snippet, | ||||
| // | ||||
| //	package painkiller | ||||
| // | ||||
| //	type Pill int | ||||
| // | ||||
| //	const ( | ||||
| //		Placebo Pill = iota | ||||
| //		Aspirin | ||||
| //		Ibuprofen | ||||
| //		Paracetamol | ||||
| //		Acetaminophen = Paracetamol | ||||
| //	) | ||||
| // | ||||
| // running this command | ||||
| // | ||||
| //	stringer -type=Pill | ||||
| // | ||||
| // in the same directory will create the file pill_string.go, in package painkiller, | ||||
| // containing a definition of | ||||
| // | ||||
| //	func (Pill) String() string | ||||
| // | ||||
| // That method will translate the value of a Pill constant to the string representation | ||||
| // of the respective constant name, so that the call fmt.Print(painkiller.Aspirin) will | ||||
| // print the string "Aspirin". | ||||
| // | ||||
| // Typically this process would be run using go generate, like this: | ||||
| // | ||||
| //	//go:generate stringer -type=Pill | ||||
| // | ||||
| // If multiple constants have the same value, the lexically first matching name will | ||||
| // be used (in the example, Acetaminophen will print as "Paracetamol"). | ||||
| // | ||||
| // With no arguments, it processes the package in the current directory. | ||||
| // Otherwise, the arguments must name a single directory holding a Go package | ||||
| // or a set of Go source files that represent a single Go package. | ||||
| // | ||||
| // The -type flag accepts a comma-separated list of types so a single run can | ||||
| // generate methods for multiple types. The default output file is t_string.go, | ||||
| // where t is the lower-cased name of the first type listed. It can be overridden | ||||
| // with the -output flag. | ||||
| // | ||||
| // The -linecomment flag tells stringer to generate the text of any line comment, trimmed | ||||
| // of leading spaces, instead of the constant name. For instance, if the constants above had a | ||||
| // Pill prefix, one could write | ||||
| // | ||||
| //	PillAspirin // Aspirin | ||||
| // | ||||
| // to suppress it in the output. | ||||
| package main // import "golang.org/x/tools/cmd/stringer" | ||||
|  | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"flag" | ||||
| 	"fmt" | ||||
| 	"go/ast" | ||||
| 	"go/constant" | ||||
| 	"go/format" | ||||
| 	"go/token" | ||||
| 	"go/types" | ||||
| 	"log" | ||||
| 	"os" | ||||
| 	"path/filepath" | ||||
| 	"sort" | ||||
| 	"strings" | ||||
|  | ||||
| 	"golang.org/x/tools/go/packages" | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| 	typeNames   = flag.String("type", "", "comma-separated list of type names; must be set") | ||||
| 	output      = flag.String("output", "", "output file name; default srcdir/<type>_string.go") | ||||
| 	trimprefix  = flag.String("trimprefix", "", "trim the `prefix` from the generated constant names") | ||||
| 	linecomment = flag.Bool("linecomment", false, "use line comment text as printed text when present") | ||||
| 	buildTags   = flag.String("tags", "", "comma-separated list of build tags to apply") | ||||
| ) | ||||
|  | ||||
| // Usage is a replacement usage function for the flags package. | ||||
| func Usage() { | ||||
| 	fmt.Fprintf(os.Stderr, "Usage of stringer:\n") | ||||
| 	fmt.Fprintf(os.Stderr, "\tstringer [flags] -type T [directory]\n") | ||||
| 	fmt.Fprintf(os.Stderr, "\tstringer [flags] -type T files... # Must be a single package\n") | ||||
| 	fmt.Fprintf(os.Stderr, "For more information, see:\n") | ||||
| 	fmt.Fprintf(os.Stderr, "\thttps://pkg.go.dev/golang.org/x/tools/cmd/stringer\n") | ||||
| 	fmt.Fprintf(os.Stderr, "Flags:\n") | ||||
| 	flag.PrintDefaults() | ||||
| } | ||||
|  | ||||
| func main() { | ||||
| 	log.SetFlags(0) | ||||
| 	log.SetPrefix("stringer: ") | ||||
| 	flag.Usage = Usage | ||||
| 	flag.Parse() | ||||
| 	if len(*typeNames) == 0 { | ||||
| 		flag.Usage() | ||||
| 		os.Exit(2) | ||||
| 	} | ||||
| 	types := strings.Split(*typeNames, ",") | ||||
| 	var tags []string | ||||
| 	if len(*buildTags) > 0 { | ||||
| 		tags = strings.Split(*buildTags, ",") | ||||
| 	} | ||||
|  | ||||
| 	// We accept either one directory or a list of files. Which do we have? | ||||
| 	args := flag.Args() | ||||
| 	if len(args) == 0 { | ||||
| 		// Default: process whole package in current directory. | ||||
| 		args = []string{"."} | ||||
| 	} | ||||
|  | ||||
| 	// Parse the package once. | ||||
| 	var dir string | ||||
| 	g := Generator{ | ||||
| 		trimPrefix:  *trimprefix, | ||||
| 		lineComment: *linecomment, | ||||
| 	} | ||||
| 	// TODO(suzmue): accept other patterns for packages (directories, list of files, import paths, etc). | ||||
| 	if len(args) == 1 && isDirectory(args[0]) { | ||||
| 		dir = args[0] | ||||
| 	} else { | ||||
| 		if len(tags) != 0 { | ||||
| 			log.Fatal("-tags option applies only to directories, not when files are specified") | ||||
| 		} | ||||
| 		dir = filepath.Dir(args[0]) | ||||
| 	} | ||||
|  | ||||
| 	g.parsePackage(args, tags) | ||||
|  | ||||
| 	// Print the header and package clause. | ||||
| 	g.Printf("// Code generated by \"stringer %s\"; DO NOT EDIT.\n", strings.Join(os.Args[1:], " ")) | ||||
| 	g.Printf("\n") | ||||
| 	g.Printf("package %s", g.pkg.name) | ||||
| 	g.Printf("\n") | ||||
| 	g.Printf("import \"strconv\"\n") // Used by all methods. | ||||
|  | ||||
| 	// Run generate for each type. | ||||
| 	for _, typeName := range types { | ||||
| 		g.generate(typeName) | ||||
| 	} | ||||
|  | ||||
| 	// Format the output. | ||||
| 	src := g.format() | ||||
|  | ||||
| 	// Write to file. | ||||
| 	outputName := *output | ||||
| 	if outputName == "" { | ||||
| 		baseName := fmt.Sprintf("%s_string.go", types[0]) | ||||
| 		outputName = filepath.Join(dir, strings.ToLower(baseName)) | ||||
| 	} | ||||
| 	err := os.WriteFile(outputName, src, 0644) | ||||
| 	if err != nil { | ||||
| 		log.Fatalf("writing output: %s", err) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // isDirectory reports whether the named file is a directory. | ||||
| func isDirectory(name string) bool { | ||||
| 	info, err := os.Stat(name) | ||||
| 	if err != nil { | ||||
| 		log.Fatal(err) | ||||
| 	} | ||||
| 	return info.IsDir() | ||||
| } | ||||
|  | ||||
| // Generator holds the state of the analysis. Primarily used to buffer | ||||
| // the output for format.Source. | ||||
| type Generator struct { | ||||
| 	buf bytes.Buffer // Accumulated output. | ||||
| 	pkg *Package     // Package we are scanning. | ||||
|  | ||||
| 	trimPrefix  string | ||||
| 	lineComment bool | ||||
| } | ||||
|  | ||||
| func (g *Generator) Printf(format string, args ...interface{}) { | ||||
| 	fmt.Fprintf(&g.buf, format, args...) | ||||
| } | ||||
|  | ||||
| // File holds a single parsed file and associated data. | ||||
| type File struct { | ||||
| 	pkg  *Package  // Package to which this file belongs. | ||||
| 	file *ast.File // Parsed AST. | ||||
| 	// These fields are reset for each type being generated. | ||||
| 	typeName string  // Name of the constant type. | ||||
| 	values   []Value // Accumulator for constant values of that type. | ||||
|  | ||||
| 	trimPrefix  string | ||||
| 	lineComment bool | ||||
| } | ||||
|  | ||||
| type Package struct { | ||||
| 	name  string | ||||
| 	defs  map[*ast.Ident]types.Object | ||||
| 	files []*File | ||||
| } | ||||
|  | ||||
| // parsePackage analyzes the single package constructed from the patterns and tags. | ||||
| // parsePackage exits if there is an error. | ||||
| func (g *Generator) parsePackage(patterns []string, tags []string) { | ||||
| 	cfg := &packages.Config{ | ||||
| 		Mode: packages.NeedName | packages.NeedTypes | packages.NeedTypesInfo | packages.NeedSyntax, | ||||
| 		// TODO: Need to think about constants in test files. Maybe write type_string_test.go | ||||
| 		// in a separate pass? For later. | ||||
| 		Tests:      false, | ||||
| 		BuildFlags: []string{fmt.Sprintf("-tags=%s", strings.Join(tags, " "))}, | ||||
| 	} | ||||
| 	pkgs, err := packages.Load(cfg, patterns...) | ||||
| 	if err != nil { | ||||
| 		log.Fatal(err) | ||||
| 	} | ||||
| 	if len(pkgs) != 1 { | ||||
| 		log.Fatalf("error: %d packages found", len(pkgs)) | ||||
| 	} | ||||
| 	g.addPackage(pkgs[0]) | ||||
| } | ||||
|  | ||||
| // addPackage adds a type checked Package and its syntax files to the generator. | ||||
| func (g *Generator) addPackage(pkg *packages.Package) { | ||||
| 	g.pkg = &Package{ | ||||
| 		name:  pkg.Name, | ||||
| 		defs:  pkg.TypesInfo.Defs, | ||||
| 		files: make([]*File, len(pkg.Syntax)), | ||||
| 	} | ||||
|  | ||||
| 	for i, file := range pkg.Syntax { | ||||
| 		g.pkg.files[i] = &File{ | ||||
| 			file:        file, | ||||
| 			pkg:         g.pkg, | ||||
| 			trimPrefix:  g.trimPrefix, | ||||
| 			lineComment: g.lineComment, | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // generate produces the String method for the named type. | ||||
| func (g *Generator) generate(typeName string) { | ||||
| 	values := make([]Value, 0, 100) | ||||
| 	for _, file := range g.pkg.files { | ||||
| 		// Set the state for this run of the walker. | ||||
| 		file.typeName = typeName | ||||
| 		file.values = nil | ||||
| 		if file.file != nil { | ||||
| 			ast.Inspect(file.file, file.genDecl) | ||||
| 			values = append(values, file.values...) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if len(values) == 0 { | ||||
| 		log.Fatalf("no values defined for type %s", typeName) | ||||
| 	} | ||||
| 	// Generate code that will fail if the constants change value. | ||||
| 	g.Printf("func _() {\n") | ||||
| 	g.Printf("\t// An \"invalid array index\" compiler error signifies that the constant values have changed.\n") | ||||
| 	g.Printf("\t// Re-run the stringer command to generate them again.\n") | ||||
| 	g.Printf("\tvar x [1]struct{}\n") | ||||
| 	for _, v := range values { | ||||
| 		g.Printf("\t_ = x[%s - %s]\n", v.originalName, v.str) | ||||
| 	} | ||||
| 	g.Printf("}\n") | ||||
| 	runs := splitIntoRuns(values) | ||||
| 	// The decision of which pattern to use depends on the number of | ||||
| 	// runs in the numbers. If there's only one, it's easy. For more than | ||||
| 	// one, there's a tradeoff between complexity and size of the data | ||||
| 	// and code vs. the simplicity of a map. A map takes more space, | ||||
| 	// but so does the code. The decision here (crossover at 10) is | ||||
| 	// arbitrary, but considers that for large numbers of runs the cost | ||||
| 	// of the linear scan in the switch might become important, and | ||||
| 	// rather than use yet another algorithm such as binary search, | ||||
| 	// we punt and use a map. In any case, the likelihood of a map | ||||
| 	// being necessary for any realistic example other than bitmasks | ||||
| 	// is very low. And bitmasks probably deserve their own analysis, | ||||
| 	// to be done some other day. | ||||
| 	switch { | ||||
| 	case len(runs) == 1: | ||||
| 		g.buildOneRun(runs, typeName) | ||||
| 	case len(runs) <= 10: | ||||
| 		g.buildMultipleRuns(runs, typeName) | ||||
| 	default: | ||||
| 		g.buildMap(runs, typeName) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // splitIntoRuns breaks the values into runs of contiguous sequences. | ||||
| // For example, given 1,2,3,5,6,7 it returns {1,2,3},{5,6,7}. | ||||
| // The input slice is known to be non-empty. | ||||
| func splitIntoRuns(values []Value) [][]Value { | ||||
| 	// We use stable sort so the lexically first name is chosen for equal elements. | ||||
| 	sort.Stable(byValue(values)) | ||||
| 	// Remove duplicates. Stable sort has put the one we want to print first, | ||||
| 	// so use that one. The String method won't care about which named constant | ||||
| 	// was the argument, so the first name for the given value is the only one to keep. | ||||
| 	// We need to do this because identical values would cause the switch or map | ||||
| 	// to fail to compile. | ||||
| 	j := 1 | ||||
| 	for i := 1; i < len(values); i++ { | ||||
| 		if values[i].value != values[i-1].value { | ||||
| 			values[j] = values[i] | ||||
| 			j++ | ||||
| 		} | ||||
| 	} | ||||
| 	values = values[:j] | ||||
| 	runs := make([][]Value, 0, 10) | ||||
| 	for len(values) > 0 { | ||||
| 		// One contiguous sequence per outer loop. | ||||
| 		i := 1 | ||||
| 		for i < len(values) && values[i].value == values[i-1].value+1 { | ||||
| 			i++ | ||||
| 		} | ||||
| 		runs = append(runs, values[:i]) | ||||
| 		values = values[i:] | ||||
| 	} | ||||
| 	return runs | ||||
| } | ||||
|  | ||||
| // format returns the gofmt-ed contents of the Generator's buffer. | ||||
| func (g *Generator) format() []byte { | ||||
| 	src, err := format.Source(g.buf.Bytes()) | ||||
| 	if err != nil { | ||||
| 		// Should never happen, but can arise when developing this code. | ||||
| 		// The user can compile the output to see the error. | ||||
| 		log.Printf("warning: internal error: invalid Go generated: %s", err) | ||||
| 		log.Printf("warning: compile the package to analyze the error") | ||||
| 		return g.buf.Bytes() | ||||
| 	} | ||||
| 	return src | ||||
| } | ||||
|  | ||||
| // Value represents a declared constant. | ||||
| type Value struct { | ||||
| 	originalName string // The name of the constant. | ||||
| 	name         string // The name with trimmed prefix. | ||||
| 	// The value is stored as a bit pattern alone. The boolean tells us | ||||
| 	// whether to interpret it as an int64 or a uint64; the only place | ||||
| 	// this matters is when sorting. | ||||
| 	// Much of the time the str field is all we need; it is printed | ||||
| 	// by Value.String. | ||||
| 	value  uint64 // Will be converted to int64 when needed. | ||||
| 	signed bool   // Whether the constant is a signed type. | ||||
| 	str    string // The string representation given by the "go/constant" package. | ||||
| } | ||||
|  | ||||
| func (v *Value) String() string { | ||||
| 	return v.str | ||||
| } | ||||
|  | ||||
| // byValue lets us sort the constants into increasing order. | ||||
| // We take care in the Less method to sort in signed or unsigned order, | ||||
| // as appropriate. | ||||
| type byValue []Value | ||||
|  | ||||
| func (b byValue) Len() int      { return len(b) } | ||||
| func (b byValue) Swap(i, j int) { b[i], b[j] = b[j], b[i] } | ||||
| func (b byValue) Less(i, j int) bool { | ||||
| 	if b[i].signed { | ||||
| 		return int64(b[i].value) < int64(b[j].value) | ||||
| 	} | ||||
| 	return b[i].value < b[j].value | ||||
| } | ||||
|  | ||||
| // genDecl processes one declaration clause. | ||||
| func (f *File) genDecl(node ast.Node) bool { | ||||
| 	decl, ok := node.(*ast.GenDecl) | ||||
| 	if !ok || decl.Tok != token.CONST { | ||||
| 		// We only care about const declarations. | ||||
| 		return true | ||||
| 	} | ||||
| 	// The name of the type of the constants we are declaring. | ||||
| 	// Can change if this is a multi-element declaration. | ||||
| 	typ := "" | ||||
| 	// Loop over the elements of the declaration. Each element is a ValueSpec: | ||||
| 	// a list of names possibly followed by a type, possibly followed by values. | ||||
| 	// If the type and value are both missing, we carry down the type (and value, | ||||
| 	// but the "go/types" package takes care of that). | ||||
| 	for _, spec := range decl.Specs { | ||||
| 		vspec := spec.(*ast.ValueSpec) // Guaranteed to succeed as this is CONST. | ||||
| 		if vspec.Type == nil && len(vspec.Values) > 0 { | ||||
| 			// "X = 1". With no type but a value. If the constant is untyped, | ||||
| 			// skip this vspec and reset the remembered type. | ||||
| 			typ = "" | ||||
|  | ||||
| 			// If this is a simple type conversion, remember the type. | ||||
| 			// We don't mind if this is actually a call; a qualified call won't | ||||
| 			// be matched (that will be SelectorExpr, not Ident), and only unusual | ||||
| 			// situations will result in a function call that appears to be | ||||
| 			// a type conversion. | ||||
| 			ce, ok := vspec.Values[0].(*ast.CallExpr) | ||||
| 			if !ok { | ||||
| 				continue | ||||
| 			} | ||||
| 			id, ok := ce.Fun.(*ast.Ident) | ||||
| 			if !ok { | ||||
| 				continue | ||||
| 			} | ||||
| 			typ = id.Name | ||||
| 		} | ||||
| 		if vspec.Type != nil { | ||||
| 			// "X T". We have a type. Remember it. | ||||
| 			ident, ok := vspec.Type.(*ast.Ident) | ||||
| 			if !ok { | ||||
| 				continue | ||||
| 			} | ||||
| 			typ = ident.Name | ||||
| 		} | ||||
| 		if typ != f.typeName { | ||||
| 			// This is not the type we're looking for. | ||||
| 			continue | ||||
| 		} | ||||
| 		// We now have a list of names (from one line of source code) all being | ||||
| 		// declared with the desired type. | ||||
| 		// Grab their names and actual values and store them in f.values. | ||||
| 		for _, name := range vspec.Names { | ||||
| 			if name.Name == "_" { | ||||
| 				continue | ||||
| 			} | ||||
| 			// This dance lets the type checker find the values for us. It's a | ||||
| 			// bit tricky: look up the object declared by the name, find its | ||||
| 			// types.Const, and extract its value. | ||||
| 			obj, ok := f.pkg.defs[name] | ||||
| 			if !ok { | ||||
| 				log.Fatalf("no value for constant %s", name) | ||||
| 			} | ||||
| 			info := obj.Type().Underlying().(*types.Basic).Info() | ||||
| 			if info&types.IsInteger == 0 { | ||||
| 				log.Fatalf("can't handle non-integer constant type %s", typ) | ||||
| 			} | ||||
| 			value := obj.(*types.Const).Val() // Guaranteed to succeed as this is CONST. | ||||
| 			if value.Kind() != constant.Int { | ||||
| 				log.Fatalf("can't happen: constant is not an integer %s", name) | ||||
| 			} | ||||
| 			i64, isInt := constant.Int64Val(value) | ||||
| 			u64, isUint := constant.Uint64Val(value) | ||||
| 			if !isInt && !isUint { | ||||
| 				log.Fatalf("internal error: value of %s is not an integer: %s", name, value.String()) | ||||
| 			} | ||||
| 			if !isInt { | ||||
| 				u64 = uint64(i64) | ||||
| 			} | ||||
| 			v := Value{ | ||||
| 				originalName: name.Name, | ||||
| 				value:        u64, | ||||
| 				signed:       info&types.IsUnsigned == 0, | ||||
| 				str:          value.String(), | ||||
| 			} | ||||
| 			if c := vspec.Comment; f.lineComment && c != nil && len(c.List) == 1 { | ||||
| 				v.name = strings.TrimSpace(c.Text()) | ||||
| 			} else { | ||||
| 				v.name = strings.TrimPrefix(v.originalName, f.trimPrefix) | ||||
| 			} | ||||
| 			f.values = append(f.values, v) | ||||
| 		} | ||||
| 	} | ||||
| 	return false | ||||
| } | ||||
|  | ||||
| // Helpers | ||||
|  | ||||
| // usize returns the number of bits of the smallest unsigned integer | ||||
| // type that will hold n. Used to create the smallest possible slice of | ||||
| // integers to use as indexes into the concatenated strings. | ||||
| func usize(n int) int { | ||||
| 	switch { | ||||
| 	case n < 1<<8: | ||||
| 		return 8 | ||||
| 	case n < 1<<16: | ||||
| 		return 16 | ||||
| 	default: | ||||
| 		// 2^32 is enough constants for anyone. | ||||
| 		return 32 | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // declareIndexAndNameVars declares the index slices and concatenated names | ||||
| // strings representing the runs of values. | ||||
| func (g *Generator) declareIndexAndNameVars(runs [][]Value, typeName string) { | ||||
| 	var indexes, names []string | ||||
| 	for i, run := range runs { | ||||
| 		index, name := g.createIndexAndNameDecl(run, typeName, fmt.Sprintf("_%d", i)) | ||||
| 		if len(run) != 1 { | ||||
| 			indexes = append(indexes, index) | ||||
| 		} | ||||
| 		names = append(names, name) | ||||
| 	} | ||||
| 	g.Printf("const (\n") | ||||
| 	for _, name := range names { | ||||
| 		g.Printf("\t%s\n", name) | ||||
| 	} | ||||
| 	g.Printf(")\n\n") | ||||
|  | ||||
| 	if len(indexes) > 0 { | ||||
| 		g.Printf("var (") | ||||
| 		for _, index := range indexes { | ||||
| 			g.Printf("\t%s\n", index) | ||||
| 		} | ||||
| 		g.Printf(")\n\n") | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // declareIndexAndNameVar is the single-run version of declareIndexAndNameVars | ||||
| func (g *Generator) declareIndexAndNameVar(run []Value, typeName string) { | ||||
| 	index, name := g.createIndexAndNameDecl(run, typeName, "") | ||||
| 	g.Printf("const %s\n", name) | ||||
| 	g.Printf("var %s\n", index) | ||||
| } | ||||
|  | ||||
| // createIndexAndNameDecl returns the pair of declarations for the run. The caller will add "const" and "var". | ||||
| func (g *Generator) createIndexAndNameDecl(run []Value, typeName string, suffix string) (string, string) { | ||||
| 	b := new(bytes.Buffer) | ||||
| 	indexes := make([]int, len(run)) | ||||
| 	for i := range run { | ||||
| 		b.WriteString(run[i].name) | ||||
| 		indexes[i] = b.Len() | ||||
| 	} | ||||
| 	nameConst := fmt.Sprintf("_%s_name%s = %q", typeName, suffix, b.String()) | ||||
| 	nameLen := b.Len() | ||||
| 	b.Reset() | ||||
| 	fmt.Fprintf(b, "_%s_index%s = [...]uint%d{0, ", typeName, suffix, usize(nameLen)) | ||||
| 	for i, v := range indexes { | ||||
| 		if i > 0 { | ||||
| 			fmt.Fprintf(b, ", ") | ||||
| 		} | ||||
| 		fmt.Fprintf(b, "%d", v) | ||||
| 	} | ||||
| 	fmt.Fprintf(b, "}") | ||||
| 	return b.String(), nameConst | ||||
| } | ||||
|  | ||||
| // declareNameVars declares the concatenated names string representing all the values in the runs. | ||||
| func (g *Generator) declareNameVars(runs [][]Value, typeName string, suffix string) { | ||||
| 	g.Printf("const _%s_name%s = \"", typeName, suffix) | ||||
| 	for _, run := range runs { | ||||
| 		for i := range run { | ||||
| 			g.Printf("%s", run[i].name) | ||||
| 		} | ||||
| 	} | ||||
| 	g.Printf("\"\n") | ||||
| } | ||||
|  | ||||
| // buildOneRun generates the variables and String method for a single run of contiguous values. | ||||
| func (g *Generator) buildOneRun(runs [][]Value, typeName string) { | ||||
| 	values := runs[0] | ||||
| 	g.Printf("\n") | ||||
| 	g.declareIndexAndNameVar(values, typeName) | ||||
| 	// The generated code is simple enough to write as a Printf format. | ||||
| 	lessThanZero := "" | ||||
| 	if values[0].signed { | ||||
| 		lessThanZero = "i < 0 || " | ||||
| 	} | ||||
| 	if values[0].value == 0 { // Signed or unsigned, 0 is still 0. | ||||
| 		g.Printf(stringOneRun, typeName, usize(len(values)), lessThanZero) | ||||
| 	} else { | ||||
| 		g.Printf(stringOneRunWithOffset, typeName, values[0].String(), usize(len(values)), lessThanZero) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // Arguments to format are: | ||||
| // | ||||
| //	[1]: type name | ||||
| //	[2]: size of index element (8 for uint8 etc.) | ||||
| //	[3]: less than zero check (for signed types) | ||||
| const stringOneRun = `func (i %[1]s) String() string { | ||||
| 	if %[3]si >= %[1]s(len(_%[1]s_index)-1) { | ||||
| 		return "%[1]s(" + strconv.FormatInt(int64(i), 10) + ")" | ||||
| 	} | ||||
| 	return _%[1]s_name[_%[1]s_index[i]:_%[1]s_index[i+1]] | ||||
| } | ||||
| ` | ||||
|  | ||||
| // Arguments to format are: | ||||
| //	[1]: type name | ||||
| //	[2]: lowest defined value for type, as a string | ||||
| //	[3]: size of index element (8 for uint8 etc.) | ||||
| //	[4]: less than zero check (for signed types) | ||||
| /* | ||||
|  */ | ||||
| const stringOneRunWithOffset = `func (i %[1]s) String() string { | ||||
| 	i -= %[2]s | ||||
| 	if %[4]si >= %[1]s(len(_%[1]s_index)-1) { | ||||
| 		return "%[1]s(" + strconv.FormatInt(int64(i + %[2]s), 10) + ")" | ||||
| 	} | ||||
| 	return _%[1]s_name[_%[1]s_index[i] : _%[1]s_index[i+1]] | ||||
| } | ||||
| ` | ||||
|  | ||||
| // buildMultipleRuns generates the variables and String method for multiple runs of contiguous values. | ||||
| // For this pattern, a single Printf format won't do. | ||||
| func (g *Generator) buildMultipleRuns(runs [][]Value, typeName string) { | ||||
| 	g.Printf("\n") | ||||
| 	g.declareIndexAndNameVars(runs, typeName) | ||||
| 	g.Printf("func (i %s) String() string {\n", typeName) | ||||
| 	g.Printf("\tswitch {\n") | ||||
| 	for i, values := range runs { | ||||
| 		if len(values) == 1 { | ||||
| 			g.Printf("\tcase i == %s:\n", &values[0]) | ||||
| 			g.Printf("\t\treturn _%s_name_%d\n", typeName, i) | ||||
| 			continue | ||||
| 		} | ||||
| 		if values[0].value == 0 && !values[0].signed { | ||||
| 			// For an unsigned lower bound of 0, "0 <= i" would be redundant. | ||||
| 			g.Printf("\tcase i <= %s:\n", &values[len(values)-1]) | ||||
| 		} else { | ||||
| 			g.Printf("\tcase %s <= i && i <= %s:\n", &values[0], &values[len(values)-1]) | ||||
| 		} | ||||
| 		if values[0].value != 0 { | ||||
| 			g.Printf("\t\ti -= %s\n", &values[0]) | ||||
| 		} | ||||
| 		g.Printf("\t\treturn _%s_name_%d[_%s_index_%d[i]:_%s_index_%d[i+1]]\n", | ||||
| 			typeName, i, typeName, i, typeName, i) | ||||
| 	} | ||||
| 	g.Printf("\tdefault:\n") | ||||
| 	g.Printf("\t\treturn \"%s(\" + strconv.FormatInt(int64(i), 10) + \")\"\n", typeName) | ||||
| 	g.Printf("\t}\n") | ||||
| 	g.Printf("}\n") | ||||
| } | ||||
|  | ||||
| // buildMap handles the case where the space is so sparse a map is a reasonable fallback. | ||||
| // It's a rare situation but has simple code. | ||||
| func (g *Generator) buildMap(runs [][]Value, typeName string) { | ||||
| 	g.Printf("\n") | ||||
| 	g.declareNameVars(runs, typeName, "") | ||||
| 	g.Printf("\nvar _%s_map = map[%s]string{\n", typeName, typeName) | ||||
| 	n := 0 | ||||
| 	for _, values := range runs { | ||||
| 		for _, value := range values { | ||||
| 			g.Printf("\t%s: _%s_name[%d:%d],\n", &value, typeName, n, n+len(value.name)) | ||||
| 			n += len(value.name) | ||||
| 		} | ||||
| 	} | ||||
| 	g.Printf("}\n\n") | ||||
| 	g.Printf(stringMap, typeName) | ||||
| } | ||||
|  | ||||
| // Argument to format is the type name. | ||||
| const stringMap = `func (i %[1]s) String() string { | ||||
| 	if str, ok := _%[1]s_map[i]; ok { | ||||
| 		return str | ||||
| 	} | ||||
| 	return "%[1]s(" + strconv.FormatInt(int64(i), 10) + ")" | ||||
| } | ||||
| ` | ||||
							
								
								
									
										6
									
								
								vendor/modules.txt
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								vendor/modules.txt
									
									
									
									
										vendored
									
									
								
							| @@ -58,9 +58,10 @@ github.com/JeffAshton/win_pdh | ||||
| # github.com/MakeNowJust/heredoc v1.0.0 | ||||
| ## explicit; go 1.12 | ||||
| github.com/MakeNowJust/heredoc | ||||
| # github.com/Microsoft/go-winio v0.4.17 | ||||
| ## explicit; go 1.12 | ||||
| # github.com/Microsoft/go-winio v0.6.0 | ||||
| ## explicit; go 1.17 | ||||
| github.com/Microsoft/go-winio | ||||
| github.com/Microsoft/go-winio/internal/socket | ||||
| github.com/Microsoft/go-winio/pkg/guid | ||||
| github.com/Microsoft/go-winio/pkg/security | ||||
| github.com/Microsoft/go-winio/vhd | ||||
| @@ -1028,6 +1029,7 @@ golang.org/x/time/rate | ||||
| # golang.org/x/tools v0.8.0 | ||||
| ## explicit; go 1.18 | ||||
| golang.org/x/tools/benchmark/parse | ||||
| golang.org/x/tools/cmd/stringer | ||||
| golang.org/x/tools/container/intsets | ||||
| golang.org/x/tools/go/ast/astutil | ||||
| golang.org/x/tools/go/ast/inspector | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Mark Rossetti
					Mark Rossetti