diff --git a/go.mod b/go.mod index 0918af54ec..f8a934223a 100644 --- a/go.mod +++ b/go.mod @@ -14,7 +14,7 @@ require ( github.com/containers/gvisor-tap-vsock v0.7.2 github.com/containers/image/v5 v5.29.0 github.com/coreos/go-systemd/v22 v22.5.0 - github.com/crc-org/admin-helper v0.0.12 + github.com/crc-org/admin-helper v0.5.2 github.com/crc-org/machine v0.0.0-20221028075518-f9b43442196b github.com/crc-org/vfkit v0.5.0 github.com/cucumber/godog v0.13.0 @@ -73,6 +73,7 @@ require ( github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d // indirect github.com/alessio/shellescape v1.4.2 // indirect github.com/apparentlymart/go-cidr v1.1.0 // indirect + github.com/areYouLazy/libhosty v1.1.0 // indirect github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 // indirect github.com/cloudflare/circl v1.3.7 // indirect github.com/containers/libtrust v0.0.0-20230121012942-c1716e8a8d01 // indirect @@ -84,7 +85,6 @@ require ( github.com/cyberphone/json-canonicalization v0.0.0-20231011164504-785e29786b46 // indirect github.com/danieljoos/wincred v1.2.0 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect - github.com/dimchansky/utfbom v1.1.1 // indirect github.com/distribution/reference v0.5.0 // indirect github.com/docker/distribution v2.8.3+incompatible // indirect github.com/docker/docker v24.0.7+incompatible // indirect @@ -112,7 +112,6 @@ require ( github.com/gofrs/uuid v4.3.1+incompatible // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/protobuf v1.5.3 // indirect - github.com/goodhosts/hostsfile v0.1.1 // indirect github.com/google/btree v1.1.2 // indirect github.com/google/gnostic v0.5.7-v3refs // indirect github.com/google/go-cmp v0.6.0 // indirect diff --git a/go.sum b/go.sum index 5aef669418..64dafca0c3 100644 --- a/go.sum +++ b/go.sum @@ -66,6 +66,8 @@ github.com/alessio/shellescape v1.4.2 h1:MHPfaU+ddJ0/bYWpgIeUnQUqKrlJ1S7BfEYPM4u github.com/alessio/shellescape v1.4.2/go.mod h1:PZAiSCk0LJaZkiCSkPv8qIobYglO3FPpyFjDCtHLS30= github.com/apparentlymart/go-cidr v1.1.0 h1:2mAhrMoF+nhXqxTzSZMUzDHkLjmIHC+Zzn4tdgBZjnU= github.com/apparentlymart/go-cidr v1.1.0/go.mod h1:EBcsNrHc3zQeuaeCeCtQruQm+n9/YjEn/vI25Lg7Gwc= +github.com/areYouLazy/libhosty v1.1.0 h1:kO6UTk9z72cHW28A/V1kKi7C8iKQGqINiVGXp+05Eao= +github.com/areYouLazy/libhosty v1.1.0/go.mod h1:dV4ir3feRrTbWdcJ21mt3MeZlASg0sc8db6nimL9GOA= github.com/armon/go-proxyproto v0.0.0-20210323213023-7e956b284f0a/go.mod h1:QmP9hvJ91BbJmGVGSbutW19IC0Q9phDCLGaomwTJbgU= github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so= @@ -100,11 +102,10 @@ github.com/containers/storage v1.51.0 h1:AowbcpiWXzAjHosKz7MKvPEqpyX+ryZA/ZurytR github.com/containers/storage v1.51.0/go.mod h1:ybl8a3j1PPtpyaEi/5A6TOFs+5TrEyObeKJzVtkUlfc= github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/corpix/uarand v0.1.1 h1:RMr1TWc9F4n5jiPDzFHtmaUXLKLNUFK0SgCLo4BhX/U= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= -github.com/crc-org/admin-helper v0.0.12 h1:CF6Ux5NwPU0dGjtDmlyl0DXbg4LiSTSu6NqUbOucHwY= -github.com/crc-org/admin-helper v0.0.12/go.mod h1:lOUnVbGyuAleeWsGo/5PTD3bI5wxQ2FUW6VDfxntppo= +github.com/crc-org/admin-helper v0.5.2 h1:ttfUSqVvHXcX1d24R/fGhzPVBMCxH/JolEqTWcaxkFE= +github.com/crc-org/admin-helper v0.5.2/go.mod h1:0rrgOlFphlxPLC9kbm0WTdjXzRP2HPwEbbO5//1cMWw= github.com/crc-org/machine v0.0.0-20221028075518-f9b43442196b h1:VPbW5D21B1WToPvEA/EGwhi4e3lXevmRff9M1lUTc5g= github.com/crc-org/machine v0.0.0-20221028075518-f9b43442196b/go.mod h1:9bEsvgLE3LIPfvGATt9Mo73gG1CKKS6A/++VqOONKqc= github.com/crc-org/vfkit v0.5.0 h1:co7N/3h5Jl29VfhPIvbF2cSG2bC7vC4DxbBVeppGPY0= @@ -130,8 +131,6 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dimchansky/utfbom v1.1.1 h1:vV6w1AhK4VMnhBno/TPVCoK9U/LP0PkLCS9tbxHdi/U= -github.com/dimchansky/utfbom v1.1.1/go.mod h1:SxdoEBH5qIqFocHMyGOXVAybYJdr71b1Q/j0mACtrfE= github.com/distribution/reference v0.5.0 h1:/FUIFXtfc/x2gpa5/VGfiGLuOIdYa1t65IKK2OFGvA0= github.com/distribution/reference v0.5.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= github.com/docker/cli v24.0.7+incompatible h1:wa/nIwYFW7BVTGa7SWPVyyXU9lgORqUb1xfI36MSkFg= @@ -286,8 +285,6 @@ github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiu github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/goodhosts/hostsfile v0.1.1 h1:SqRUTFOshOCon0ZSXDrW1bkKZvs4+5pRgYFWySdaLno= -github.com/goodhosts/hostsfile v0.1.1/go.mod h1:lXcUP8xO4WR5vvuQ3F/N0bMQoclOtYKEEUnyY2jTusY= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU= @@ -375,7 +372,6 @@ github.com/honeycombio/libhoney-go v1.16.0 h1:kPpqoz6vbOzgp7jC6SR7SkNj7rua7rgxvz github.com/hugelgupf/socketpair v0.0.0-20190730060125-05d35a94e714/go.mod h1:2Goc3h8EklBH5mspfHFxBnEoURQCGzQQH1ga9Myjvis= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/icrowley/fake v0.0.0-20180203215853-4178557ae428 h1:Mo9W14pwbO9VfRe+ygqZ8dFbPpoIK1HFrG/zjTuQ+nc= github.com/imdario/mergo v0.3.13 h1:lFzP57bqS/wsqKssCGmtLAb8A0wKjLGrve2q3PPVcBk= github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK2O4oXg= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= diff --git a/vendor/github.com/areYouLazy/libhosty/.gitignore b/vendor/github.com/areYouLazy/libhosty/.gitignore new file mode 100644 index 0000000000..d99b587513 --- /dev/null +++ b/vendor/github.com/areYouLazy/libhosty/.gitignore @@ -0,0 +1,5 @@ +# test coverage output +./coverage.out +./cover.out +coverage.out +cover.out diff --git a/vendor/github.com/dimchansky/utfbom/LICENSE b/vendor/github.com/areYouLazy/libhosty/LICENSE similarity index 99% rename from vendor/github.com/dimchansky/utfbom/LICENSE rename to vendor/github.com/areYouLazy/libhosty/LICENSE index 6279cb87f4..261eeb9e9f 100644 --- a/vendor/github.com/dimchansky/utfbom/LICENSE +++ b/vendor/github.com/areYouLazy/libhosty/LICENSE @@ -178,7 +178,7 @@ APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "{}" + boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a @@ -186,7 +186,7 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright (c) 2018-2020, Dmitrij Koniajev (dimchansky@gmail.com) + Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/vendor/github.com/areYouLazy/libhosty/README.md b/vendor/github.com/areYouLazy/libhosty/README.md new file mode 100644 index 0000000000..e87c798b3e --- /dev/null +++ b/vendor/github.com/areYouLazy/libhosty/README.md @@ -0,0 +1,167 @@ +# libhosty + +[![made-with-Go](https://img.shields.io/badge/made%20with-Go-1f425f.svg)](http://golang.org) +[![Go Report Card](https://goreportcard.com/badge/github.com/areYouLazy/libhosty)](https://goreportcard.com/report/github.com/areYouLazy/libhosty) +[![Build and Test](https://github.com/areYouLazy/libhosty/actions/workflows/build-and-test.yml/badge.svg?branch=main&event=push)](https://github.com/areYouLazy/libhosty/actions/workflows/build-and-test.yml) +![gopherbadger-tag-do-not-edit](coverage_badge.png) +[![GoDoc](https://img.shields.io/badge/godoc-reference-blue.svg)](https://godoc.org/github.com/areYouLazy/libhosty) + +## Description + +libhosty is a pure golang library to manipulate the hosts file. It is inspired by [txeh](https://github.com/txn2/txeh), with some enrichments. + +## Table of Contents + +* [Main Features](#Main-Features) +* [Installation](#Installation) +* [Usage](#Usage) +* [Contributing](#Contributing) + * [Templates](#Templates) +* [Credits](#Credits) +* [License](#License) + +## Main Features + +* Comment/Uncomment a line without removing it from the file +* Restore the default hosts file for your system +* Add/Remove Address lines +* Add/Remove Comment lines +* Add/Remove Empty lines +* Query by hostname +* Automatically handles duplicate entries + +## Installation + +Ensure you have go on your system + +```bash +> go version +go version go1.15.6 linux/amd64 +``` + +and pull the library + +```bash +> go get github.com/areYouLazy/libhosty +``` + +## Usage + +To use the library, just import it and call the `Init()` method. + +Note: This code doesn't handle errors for readability purposes, but you SHOULD! + +```go +package main + +import "github.com/areYouLazy/libhosty" + +func main() { + //you can define a custom config object + // and use it to initialize libhosty with a custom hosts file + // + //cnf, _ := libhosty.NewHostsFileConfig("/home/sonica/hosts-export.txt") + //hfl, _ := libhosty.InitWithConfig(cnf) + + //or initialize libhosty that will automatically try to loads + // then default hosts file for your OS + hfl, _ := libhosty.Init() + + //add an empty line + hfl.AddEmptyFileLine() + + //add a host with a comment + hfl.AddHostFileLine("12.12.12.12", "my.host.name", "comment on my hostname!") + + //add a comment + hfl.AddCommentFileLine("just a comment") + + //add an empty line + hfl.AddEmptyFileLine() + + //add another host without comment + hfl.AddHostsFileLine("13.13.13.13", "another.host.name", "") + + //add another fqdn to the previous ip + hfl.AddHostsFileLine("12.12.12.12", "second.host.name", "") + + // comment for host lines can be done by hostname, row line + // or IP (as net.IP or string) + // + // Comment the line with address 12.12.12.12 + // + // By-Row-Number + idx, _ := hfl.GetHostsFileLineByHostname("second.host.name") + hfl.CommentHostsFileLineByRow(idx) + // + // By-Hostname + hfl.CommentHostsFileLineByHostname("second.host.name") + // + // By-Address-As-IP + ip := net.ParseIP("12.12.12.12") + hfl.CommentHostsFileLineByIP(ip) + // + // By-Address-As-String + hfl.CommentHostsFileLineByAddress("12.12.12.12") + + // render the hosts file + fmt.Println(hfl.RenderHostsFile()) + + // write file to disk + hfl.SaveHostsFile() + + // or to a custom location + hfl.SaveHostsFileAs("/home/sonica/hosts-export.txt") + + // restore the original hosts file for linux + hfl.RestoreDefaultLinuxHostsFile() + + // render the hosts file + fmt.Println(hfl.RenderHostsFile()) + + // write to disk + hfl.SaveHostsFile() +} +``` + +The 1st `fmt.Println()` should output something like this (in a linux host) + +```console +# Do not remove the following line, or various programs +# that require network functionality will fail. +127.0.0.1 localhost.localdomain localhost +::1 localhost6.localdomain6 localhost6 + +# 12.12.12.12 my.host.name second.host.name #comment on my hostname! +# just a comment line + +13.13.13.13 another.host.name +``` + +While the 2nd `fmt.Println()` should output the default template for linux systems + +```console +# Do not remove the following line, or various programs +# that require network functionality will fail. +127.0.0.1 localhost.localdomain localhost +::1 localhost6.localdomain6 localhost6 + +``` + +If you handle errors properly, you'll notice that this example program will fail on the `SaveHostsFile()` call if started as a normal user, as editing the hosts file requires root privileges. This does not prevent libhosty from loading, managing, rendering and exporting the hosts file + +## Contributing + +Issues and PRs are more than welcome! + +### Templates + +If you find a hosts template (like the Docker one) that you think can be useful to have in this library feel free to open a Pull Request + +## Credits + +Project Contributors will be listed here + +## License + +Licenses under Apache License 2.0 diff --git a/vendor/github.com/areYouLazy/libhosty/TODO.md b/vendor/github.com/areYouLazy/libhosty/TODO.md new file mode 100644 index 0000000000..136bb9f491 --- /dev/null +++ b/vendor/github.com/areYouLazy/libhosty/TODO.md @@ -0,0 +1,4 @@ +# TODO + +* Improve tests +* Improve comments diff --git a/vendor/github.com/areYouLazy/libhosty/coverage_badge.png b/vendor/github.com/areYouLazy/libhosty/coverage_badge.png new file mode 100644 index 0000000000..14cc422ee8 Binary files /dev/null and b/vendor/github.com/areYouLazy/libhosty/coverage_badge.png differ diff --git a/vendor/github.com/areYouLazy/libhosty/errors.go b/vendor/github.com/areYouLazy/libhosty/errors.go new file mode 100644 index 0000000000..d4fae1a1dc --- /dev/null +++ b/vendor/github.com/areYouLazy/libhosty/errors.go @@ -0,0 +1,38 @@ +package libhosty + +import ( + "errors" + "fmt" +) + +//ErrNotAnAddressLine used when operating on a non-address line for operation +// related to address lines, such as comment/uncomment +var ErrNotAnAddressLine = errors.New("this line is not of type ADDRESS") + +//ErrUncommentableLine used when try to comment a line that cannot be commented +var ErrUncommentableLine = errors.New("this line cannot be commented") + +//ErrAlredyCommentedLine used when try to comment an alredy commented line +var ErrAlredyCommentedLine = errors.New("this line is alredy commented") + +//ErrAlredyUncommentedLine used when try to uncomment an alredy uncommented line +var ErrAlredyUncommentedLine = errors.New("this line is alredy uncommented") + +//ErrAddressNotFound used when provided address is not found +var ErrAddressNotFound = errors.New("cannot find a line with given address") + +//ErrHostnameNotFound used when provided hostname is not found +var ErrHostnameNotFound = errors.New("cannot find a line with given hostname") + +//ErrUnknown used when we don't know what's happened +var ErrUnknown = errors.New("unknown error") + +//ErrCannotParseIPAddress used when unable to parse given ip address +func ErrCannotParseIPAddress(ip string) error { + return fmt.Errorf("cannot parse IP Address: %s", ip) +} + +//ErrUnrecognizedOS used when unable to recognize OS +func ErrUnrecognizedOS(os string) error { + return fmt.Errorf("unrecognized OS: %s", os) +} diff --git a/vendor/github.com/areYouLazy/libhosty/formatter.go b/vendor/github.com/areYouLazy/libhosty/formatter.go new file mode 100644 index 0000000000..994e5bd319 --- /dev/null +++ b/vendor/github.com/areYouLazy/libhosty/formatter.go @@ -0,0 +1,33 @@ +package libhosty + +import ( + "fmt" + "strings" +) + +// lineFormatter return a readable form for the given HostsFileLine object +func lineFormatter(hfl HostsFileLine) string { + + // returns raw if we don't need to edit the line + // this is for UNKNOWN, EMPTY and COMMENT linetypes + if hfl.Type < LineTypeAddress { + return hfl.Raw + } + + // check if it's a commented line + if hfl.IsCommented { + // check if there's a comment for that line + if len(hfl.Comment) > 0 { + return fmt.Sprintf("# %-16s %s #%s", hfl.Address, strings.Join(hfl.Hostnames, " "), hfl.Comment) + } + + return fmt.Sprintf("# %-16s %s", hfl.Address, strings.Join(hfl.Hostnames, " ")) + } + + // return the actual hosts entry + if len(hfl.Comment) > 0 { + return fmt.Sprintf("%-16s %s #%s", hfl.Address, strings.Join(hfl.Hostnames, " "), hfl.Comment) + } + + return fmt.Sprintf("%-16s %s", hfl.Address, strings.Join(hfl.Hostnames, " ")) +} diff --git a/vendor/github.com/areYouLazy/libhosty/helper.go b/vendor/github.com/areYouLazy/libhosty/helper.go new file mode 100644 index 0000000000..705916af42 --- /dev/null +++ b/vendor/github.com/areYouLazy/libhosty/helper.go @@ -0,0 +1,25 @@ +package libhosty + +//RestoreDefaultWindowsHostsFile loads the default windows hosts file +func (h *HostsFile) RestoreDefaultWindowsHostsFile() { + hfl, _ := ParseHostsFileAsString(windowsHostsTemplate) + h.HostsFileLines = hfl +} + +//RestoreDefaultLinuxHostsFile loads the default linux hosts file +func (h *HostsFile) RestoreDefaultLinuxHostsFile() { + hfl, _ := ParseHostsFileAsString(linuxHostsTemplate) + h.HostsFileLines = hfl +} + +//RestoreDefaultDarwinHostsFile loads the default darwin hosts file +func (h *HostsFile) RestoreDefaultDarwinHostsFile() { + hfl, _ := ParseHostsFileAsString(darwinHostsTemplate) + h.HostsFileLines = hfl +} + +//AddDockerDesktopTemplate adds the dockerDesktopTemplate to the actual hostsFile +func (h *HostsFile) AddDockerDesktopTemplate() { + hfl, _ := ParseHostsFileAsString(dockerDesktopTemplate) + h.HostsFileLines = append(h.HostsFileLines, hfl...) +} diff --git a/vendor/github.com/areYouLazy/libhosty/libhosty.go b/vendor/github.com/areYouLazy/libhosty/libhosty.go new file mode 100644 index 0000000000..3504e8b841 --- /dev/null +++ b/vendor/github.com/areYouLazy/libhosty/libhosty.go @@ -0,0 +1,846 @@ +//Package libhosty is a pure golang library to manipulate the hosts file +package libhosty + +import ( + "io/ioutil" + "net" + "os" + "regexp" + "runtime" + "strings" + "sync" +) + +const ( + //Version exposes library version + Version = "2.0" +) + +const ( + // defines default path for windows os + windowsFilePath = "C:\\Windows\\System32\\drivers\\etc\\" + + // defines default path for linux os + unixFilePath = "/etc/" + + // defines default filename + hostsFileName = "hosts" +) + +//LineType define a safe type for line type enumeration +type LineType int + +const ( + //LineTypeUnknown defines unknown lines + LineTypeUnknown LineType = 0 + + //LineTypeEmpty defines empty lines + LineTypeEmpty LineType = 10 + + //LineTypeComment defines comment lines (starts with #) + LineTypeComment LineType = 20 + + //LineTypeAddress defines address lines (actual hosts lines) + LineTypeAddress LineType = 30 +) + +//HostsFileConfig defines parameters to find hosts file. +// FilePath is the absolute path of the hosts file (filename included) +type HostsFileConfig struct { + FilePath string +} + +//HostsFileLine holds hosts file lines data +type HostsFileLine struct { + //Number is the original line number + Number int + + //LineType defines the line type + Type LineType + + //Address is a net.IP representation of the address + Address net.IP + + //Parts is a slice of the line splitted by '#' + Parts []string + + //Hostnames is a slice of hostnames for the relative IP + Hostnames []string + + //Raw is the raw representation of the line, as it is in the hosts file + Raw string + + //Comment is the comment part of the line (if present in an ADDRESS line) + Comment string + + //IsCommented to know if the current ADDRESS line is commented out (starts with '#') + IsCommented bool + + //trimed is a trimed version (no spaces before and after) of the line + trimed string +} + +//HostsFile is a reference for the hosts file configuration and lines +type HostsFile struct { + sync.Mutex + + //Config reference to a HostsConfig object + Config *HostsFileConfig + + //HostsFileLines slice of HostsFileLine objects + HostsFileLines []HostsFileLine +} + +//InitWithConfig returns a new instance of a hostsfile. +// InitWithConfig is meant to be used with a custom conf file +// however InitWithConfig() will fallback to Init() if conf is nill +// You should use Init() to load hosts file from default location +func InitWithConfig(conf *HostsFileConfig) (*HostsFile, error) { + var config *HostsFileConfig + var err error + + if conf != nil { + config = conf + } else { + return Init() + } + + // allocate a new HostsFile object + hf := &HostsFile{ + // use default configuration + Config: config, + + // allocate a new slice of HostsFileLine objects + HostsFileLines: make([]HostsFileLine, 0), + } + + // parse the hosts file and load file lines + hf.HostsFileLines, err = ParseHostsFile(hf.Config.FilePath) + if err != nil { + return nil, err + } + + //return HostsFile + return hf, nil +} + +//Init returns a new instance of a hostsfile. +func Init() (*HostsFile, error) { + // initialize hostsConfig + config, err := NewHostsFileConfig("") + if err != nil { + return nil, err + } + + // allocate a new HostsFile object + hf := &HostsFile{ + // use default configuration + Config: config, + + // allocate a new slice of HostsFileLine objects + HostsFileLines: make([]HostsFileLine, 0), + } + + // parse the hosts file and load file lines + hf.HostsFileLines, err = ParseHostsFile(hf.Config.FilePath) + if err != nil { + return nil, err + } + + //return HostsFile + return hf, nil +} + +//NewHostsFileConfig loads hosts file based on environment. +// NewHostsFileConfig initialize the default file path based +// on the OS or from a given location if a custom path is provided +func NewHostsFileConfig(path string) (*HostsFileConfig, error) { + // allocate hostsConfig + var hc *HostsFileConfig + + // ensure custom path exists + // https://stackoverflow.com/questions/12518876/how-to-check-if-a-file-exists-in-go + if fh, err := os.Stat(path); err == nil { + // eusure custom path points to a file (not a directory) + if !fh.IsDir() { + hc = &HostsFileConfig{ + FilePath: path, + } + } + } else { + // check os to construct default path + switch runtime.GOOS { + case "windows": + hc = &HostsFileConfig{ + FilePath: windowsFilePath + hostsFileName, + } + default: + hc = &HostsFileConfig{ + FilePath: unixFilePath + hostsFileName, + } + } + } + + return hc, nil +} + +//GetHostsFileLines returns every address row +func (h *HostsFile) GetHostsFileLines() []*HostsFileLine { + var hfl []*HostsFileLine + + for idx := range h.HostsFileLines { + if h.HostsFileLines[idx].Type == LineTypeAddress { + hfl = append(hfl, h.GetHostsFileLineByRow(idx)) + } + } + + return hfl +} + +//GetHostsFileLineByRow returns a ponter to the given HostsFileLine row +func (h *HostsFile) GetHostsFileLineByRow(row int) *HostsFileLine { + return &h.HostsFileLines[row] +} + +//GetHostsFileLineByIP returns the index of the line and a ponter to the given HostsFileLine line +func (h *HostsFile) GetHostsFileLineByIP(ip net.IP) (int, *HostsFileLine) { + if ip == nil { + return -1, nil + } + + for idx := range h.HostsFileLines { + if net.IP.Equal(ip, h.HostsFileLines[idx].Address) { + return idx, &h.HostsFileLines[idx] + } + } + + return -1, nil +} + +func (h *HostsFile) GetHostsFileLinesByIP(ip net.IP) []*HostsFileLine { + if ip == nil { + return nil + } + + hfl := make([]*HostsFileLine, 0) + + for idx := range h.HostsFileLines { + if net.IP.Equal(ip, h.HostsFileLines[idx].Address) { + hfl = append(hfl, &h.HostsFileLines[idx]) + } + } + + return hfl +} + +//GetHostsFileLineByAddress returns the index of the line and a ponter to the given HostsFileLine line +func (h *HostsFile) GetHostsFileLineByAddress(address string) (int, *HostsFileLine) { + ip := net.ParseIP(address) + return h.GetHostsFileLineByIP(ip) +} + +func (h *HostsFile) GetHostsFileLinesByAddress(address string) []*HostsFileLine { + ip := net.ParseIP(address) + return h.GetHostsFileLinesByIP(ip) +} + +//GetHostsFileLineByHostname returns the index of the line and a ponter to the given HostsFileLine line +func (h *HostsFile) GetHostsFileLineByHostname(hostname string) (int, *HostsFileLine) { + for idx := range h.HostsFileLines { + for _, hn := range h.HostsFileLines[idx].Hostnames { + if hn == hostname { + return idx, &h.HostsFileLines[idx] + } + } + } + + return -1, nil +} + +func (h *HostsFile) GetHostsFileLinesByHostname(hostname string) []*HostsFileLine { + hfl := make([]*HostsFileLine, 0) + + for idx := range h.HostsFileLines { + for _, hn := range h.HostsFileLines[idx].Hostnames { + if hn == hostname { + hfl = append(hfl, &h.HostsFileLines[idx]) + continue + } + } + } + + return hfl +} + +func (h *HostsFile) GetHostsFileLinesByHostnameAsRegexp(hostname string) []*HostsFileLine { + hfl := make([]*HostsFileLine, 0) + + reg := regexp.MustCompile(hostname) + + for idx := range h.HostsFileLines { + for _, hn := range h.HostsFileLines[idx].Hostnames { + if reg.MatchString(hn) { + hfl = append(hfl, &h.HostsFileLines[idx]) + continue + } + } + } + + return hfl +} + +//RenderHostsFile render and returns the hosts file with the lineFormatter() routine +func (h *HostsFile) RenderHostsFile() string { + // allocate a buffer for file lines + var sliceBuffer []string + + // iterate HostsFileLines and popolate the buffer with formatted lines + for _, l := range h.HostsFileLines { + sliceBuffer = append(sliceBuffer, lineFormatter(l)) + } + + // strings.Join() prevent the last line from being a new blank line + // as opposite to a for loop with fmt.Printf(buffer + '\n') + return strings.Join(sliceBuffer, "\n") +} + +//RenderHostsFileLine render and returns the given hosts line with the lineFormatter() routine +func (h *HostsFile) RenderHostsFileLine(row int) string { + // iterate to find the row to render + if len(h.HostsFileLines) > row { + return lineFormatter(h.HostsFileLines[row]) + } + + return "" +} + +//SaveHostsFile write hosts file to configured path. +// error is not nil if something goes wrong +func (h *HostsFile) SaveHostsFile() error { + return h.SaveHostsFileAs(h.Config.FilePath) +} + +//SaveHostsFileAs write hosts file to the given path. +// error is not nil if something goes wrong +func (h *HostsFile) SaveHostsFileAs(path string) error { + // render the file as a byte slice + dataBytes := []byte(h.RenderHostsFile()) + + // write file to disk + err := ioutil.WriteFile(path, dataBytes, 0644) + if err != nil { + return err + } + + return nil +} + +//RemoveHostsFileLineByRow remove row at given index from HostsFileLines +func (h *HostsFile) RemoveHostsFileLineByRow(row int) { + // prevent out-of-index + if row < len(h.HostsFileLines) { + h.Lock() + h.HostsFileLines = append(h.HostsFileLines[:row], h.HostsFileLines[row+1:]...) + h.Unlock() + } +} + +func (h *HostsFile) RemoveHostsFileLineByIP(ip net.IP) { + for idx := len(h.HostsFileLines) - 1; idx >= 0; idx-- { + if net.IP.Equal(ip, h.HostsFileLines[idx].Address) { + h.RemoveHostsFileLineByRow(idx) + return + } + } +} + +func (h *HostsFile) RemoveHostsFileLinesByIP(ip net.IP) { + for idx := len(h.HostsFileLines) - 1; idx >= 0; idx-- { + if net.IP.Equal(ip, h.HostsFileLines[idx].Address) { + h.RemoveHostsFileLineByRow(idx) + } + } +} + +func (h *HostsFile) RemoveHostsFileLineByAddress(address string) { + ip := net.ParseIP(address) + + h.RemoveHostsFileLineByIP(ip) +} + +func (h *HostsFile) RemoveHostsFileLinesByAddress(address string) { + ip := net.ParseIP(address) + + h.RemoveHostsFileLinesByIP(ip) +} + +func (h *HostsFile) RemoveHostsFileLineByHostname(hostname string) { + for idx := len(h.HostsFileLines) - 1; idx >= 0; idx-- { + if h.HostsFileLines[idx].Type == LineTypeAddress { + for _, hn := range h.HostsFileLines[idx].Hostnames { + if hn == hostname { + h.RemoveHostsFileLineByRow(idx) + return + } + } + } + } +} + +func (h *HostsFile) RemoveHostsFileLinesByHostnameAsRegexp(hostname string) { + reg := regexp.MustCompile(hostname) + + for idx := len(h.HostsFileLines) - 1; idx >= 0; idx-- { + for _, hn := range h.HostsFileLines[idx].Hostnames { + if reg.MatchString(hn) { + h.RemoveHostsFileLineByRow(idx) + continue + } + } + } +} + +func (h *HostsFile) RemoveHostsFileLinesByHostname(hostname string) { + for idx := len(h.HostsFileLines) - 1; idx >= 0; idx-- { + if h.HostsFileLines[idx].Type == LineTypeAddress { + for _, hn := range h.HostsFileLines[idx].Hostnames { + if hn == hostname { + h.RemoveHostsFileLineByRow(idx) + continue + } + } + } + } +} + +//LookupByHostname check if the given fqdn exists. +// if yes, it returns the index of the address and the associated address. +// error is not nil if something goes wrong +func (h *HostsFile) LookupByHostname(hostname string) (int, net.IP, error) { + for idx, hfl := range h.HostsFileLines { + for _, hn := range hfl.Hostnames { + if hn == hostname { + return idx, h.HostsFileLines[idx].Address, nil + } + } + } + + return -1, nil, ErrHostnameNotFound +} + +//AddHostsFileLineRaw add the given ip/fqdn/comment pair +// this is different from AddHostFileLine because it does not take care of duplicates +// this just append the new entry to the hosts file +func (h *HostsFile) AddHostsFileLineRaw(ipRaw, fqdnRaw, comment string) (int, *HostsFileLine, error) { + // hostname to lowercase + hostname := strings.ToLower(fqdnRaw) + // parse ip to net.IP + ip := net.ParseIP(ipRaw) + + // if we have a valid IP + if ip != nil { + // create a new hosts line + hfl := HostsFileLine{ + Type: LineTypeAddress, + Address: ip, + Hostnames: []string{hostname}, + Comment: comment, + IsCommented: false, + } + + // append to hosts + h.HostsFileLines = append(h.HostsFileLines, hfl) + + // get index + idx := len(h.HostsFileLines) - 1 + + // return created entry + return idx, &h.HostsFileLines[idx], nil + } + + // return error + return -1, nil, ErrCannotParseIPAddress(ipRaw) +} + +//AddHostsFileLine add the given ip/fqdn/comment pair, cleanup is done for previous entry. +// it returns the index of the edited (created) line and a pointer to the hostsfileline object. +// error is not nil if something goes wrong +func (h *HostsFile) AddHostsFileLine(ipRaw, fqdnRaw, comment string) (int, *HostsFileLine, error) { + // hostname to lowercase + hostname := strings.ToLower(fqdnRaw) + // parse ip to net.IP + ip := net.ParseIP(ipRaw) + + // if we have a valid IP + if ip != nil { + //check if we alredy have the fqdn + if idx, addr, err := h.LookupByHostname(hostname); err == nil { + //if actual ip is the same as the given one, we are done + if net.IP.Equal(addr, ip) { + // handle comment + if comment != "" { + // just replace the current comment with the new one + h.HostsFileLines[idx].Comment = comment + } + return idx, &h.HostsFileLines[idx], nil + } + + //if address is different, we need to remove the hostname from the previous entry + for hostIdx, hn := range h.HostsFileLines[idx].Hostnames { + if hn == hostname { + if len(h.HostsFileLines[idx].Hostnames) > 1 { + h.Lock() + h.HostsFileLines[idx].Hostnames = append(h.HostsFileLines[idx].Hostnames[:hostIdx], h.HostsFileLines[idx].Hostnames[hostIdx+1:]...) + h.Unlock() + } + + //remove the line if there are no more hostnames (other than the actual one) + if len(h.HostsFileLines[idx].Hostnames) <= 1 { + h.RemoveHostsFileLineByRow(idx) + } + } + } + } + + //if we alredy have the address, just add the hostname to that line + for idx, hfl := range h.HostsFileLines { + if net.IP.Equal(hfl.Address, ip) { + h.Lock() + h.HostsFileLines[idx].Hostnames = append(h.HostsFileLines[idx].Hostnames, hostname) + h.Unlock() + + // handle comment + if comment != "" { + // just replace the current comment with the new one + h.HostsFileLines[idx].Comment = comment + } + + // return edited entry + return idx, &h.HostsFileLines[idx], nil + } + } + + // at this point we need to create new host line + hfl := HostsFileLine{ + Type: LineTypeAddress, + Address: ip, + Hostnames: []string{hostname}, + Comment: comment, + IsCommented: false, + } + + // generate raw version of the line + hfl.Raw = lineFormatter(hfl) + + // append to hosts + h.HostsFileLines = append(h.HostsFileLines, hfl) + + // get index + idx := len(h.HostsFileLines) - 1 + + // return created entry + return idx, &h.HostsFileLines[idx], nil + } + + // return error + return -1, nil, ErrCannotParseIPAddress(ipRaw) +} + +//AddCommentFileLine adds a new line of type comment with the given comment. +// it returns the index of the edited (created) line and a pointer to the hostsfileline object. +// error is not nil if something goes wrong +func (h *HostsFile) AddCommentFileLine(comment string) (int, *HostsFileLine, error) { + h.Lock() + defer h.Unlock() + + hfl := HostsFileLine{ + Type: LineTypeComment, + Raw: "# " + comment, + Comment: comment, + } + + hfl.Raw = lineFormatter(hfl) + + h.HostsFileLines = append(h.HostsFileLines, hfl) + idx := len(h.HostsFileLines) - 1 + return idx, &h.HostsFileLines[idx], nil +} + +//AddEmptyFileLine adds a new line of type empty. +// it returns the index of the edited (created) line and a pointer to the hostsfileline object. +// error is not nil if something goes wrong +func (h *HostsFile) AddEmptyFileLine() (int, *HostsFileLine, error) { + h.Lock() + defer h.Unlock() + + hfl := HostsFileLine{ + Type: LineTypeEmpty, + Raw: "", + } + + h.HostsFileLines = append(h.HostsFileLines, hfl) + idx := len(h.HostsFileLines) - 1 + return idx, &h.HostsFileLines[idx], nil +} + +//CommentHostsFileLineByRow set the IsCommented bit for the given row to true +func (h *HostsFile) CommentHostsFileLineByRow(row int) error { + h.Lock() + defer h.Unlock() + + if len(h.HostsFileLines) > row { + if h.HostsFileLines[row].Type == LineTypeAddress { + if !h.HostsFileLines[row].IsCommented { + h.HostsFileLines[row].IsCommented = true + + h.HostsFileLines[row].Raw = h.RenderHostsFileLine(row) + return nil + } + + return ErrAlredyCommentedLine + } + + return ErrNotAnAddressLine + } + + return ErrUnknown +} + +//CommentHostsFileLineByIP set the IsCommented bit for the given address to true +func (h *HostsFile) CommentHostsFileLineByIP(ip net.IP) error { + h.Lock() + defer h.Unlock() + + for idx := range h.HostsFileLines { + if net.IP.Equal(ip, h.HostsFileLines[idx].Address) { + if !h.HostsFileLines[idx].IsCommented { + h.HostsFileLines[idx].IsCommented = true + + h.HostsFileLines[idx].Raw = h.RenderHostsFileLine(idx) + return nil + } + + return ErrAlredyCommentedLine + } + } + + return ErrAddressNotFound +} + +func (h *HostsFile) CommentHostsFileLinesByIP(ip net.IP) { + h.Lock() + defer h.Unlock() + + for idx := range h.HostsFileLines { + if net.IP.Equal(ip, h.HostsFileLines[idx].Address) { + if !h.HostsFileLines[idx].IsCommented { + h.HostsFileLines[idx].IsCommented = true + + h.HostsFileLines[idx].Raw = h.RenderHostsFileLine(idx) + } + } + } +} + +//CommentHostsFileLineByAddress set the IsCommented bit for the given address as string to true +func (h *HostsFile) CommentHostsFileLineByAddress(address string) error { + ip := net.ParseIP(address) + + return h.CommentHostsFileLineByIP(ip) +} + +func (h *HostsFile) CommentHostsFileLinesByAddress(address string) { + ip := net.ParseIP(address) + h.CommentHostsFileLinesByIP(ip) +} + +//CommentHostsFileLineByHostname set the IsCommented bit for the given hostname to true +func (h *HostsFile) CommentHostsFileLineByHostname(hostname string) error { + h.Lock() + defer h.Unlock() + + for idx := range h.HostsFileLines { + for _, hn := range h.HostsFileLines[idx].Hostnames { + if hn == hostname { + if !h.HostsFileLines[idx].IsCommented { + h.HostsFileLines[idx].IsCommented = true + + h.HostsFileLines[idx].Raw = h.RenderHostsFileLine(idx) + return nil + } + + return ErrAlredyCommentedLine + } + } + } + + return ErrHostnameNotFound +} + +func (h *HostsFile) CommentHostsFileLinesByHostname(hostname string) { + h.Lock() + defer h.Unlock() + + for idx := range h.HostsFileLines { + for _, hn := range h.HostsFileLines[idx].Hostnames { + if hn == hostname { + if !h.HostsFileLines[idx].IsCommented { + h.HostsFileLines[idx].IsCommented = true + + h.HostsFileLines[idx].Raw = h.RenderHostsFileLine(idx) + } + } + } + } +} + +func (h *HostsFile) CommentHostsFileLinesByHostnameAsRegexp(hostname string) { + h.Lock() + defer h.Unlock() + + reg := regexp.MustCompile(hostname) + + for idx := range h.HostsFileLines { + for _, hn := range h.HostsFileLines[idx].Hostnames { + if reg.MatchString(hn) { + if !h.HostsFileLines[idx].IsCommented { + h.HostsFileLines[idx].IsCommented = true + + h.HostsFileLines[idx].Raw = h.RenderHostsFileLine(idx) + continue + } + } + } + } +} + +//UncommentHostsFileLineByRow set the IsCommented bit for the given row to false +func (h *HostsFile) UncommentHostsFileLineByRow(row int) error { + h.Lock() + defer h.Unlock() + + if len(h.HostsFileLines) > row { + if h.HostsFileLines[row].Type == LineTypeAddress { + if h.HostsFileLines[row].IsCommented { + h.HostsFileLines[row].IsCommented = false + + h.HostsFileLines[row].Raw = h.RenderHostsFileLine(row) + return nil + } + + return ErrAlredyUncommentedLine + } + + return ErrNotAnAddressLine + } + + return ErrUnknown +} + +//UncommentHostsFileLineByIP set the IsCommented bit for the given address to false +func (h *HostsFile) UncommentHostsFileLineByIP(ip net.IP) error { + h.Lock() + defer h.Unlock() + + for idx, hfl := range h.HostsFileLines { + if net.IP.Equal(ip, hfl.Address) { + if h.HostsFileLines[idx].IsCommented { + h.HostsFileLines[idx].IsCommented = false + + h.HostsFileLines[idx].Raw = h.RenderHostsFileLine(idx) + return nil + } + + return ErrAlredyUncommentedLine + } + } + + return ErrNotAnAddressLine +} + +func (h *HostsFile) UncommentHostsFileLinesByIP(ip net.IP) { + h.Lock() + defer h.Unlock() + + for idx := range h.HostsFileLines { + if net.IP.Equal(ip, h.HostsFileLines[idx].Address) { + if h.HostsFileLines[idx].IsCommented { + h.HostsFileLines[idx].IsCommented = false + + h.HostsFileLines[idx].Raw = h.RenderHostsFileLine(idx) + } + } + } +} + +//UncommentHostsFileLineByAddress set the IsCommented bit for the given address as string to false +func (h *HostsFile) UncommentHostsFileLineByAddress(address string) error { + ip := net.ParseIP(address) + + return h.UncommentHostsFileLineByIP(ip) +} + +func (h *HostsFile) UncommentHostsFileLinesByAddress(address string) { + ip := net.ParseIP(address) + h.UncommentHostsFileLinesByIP(ip) +} + +//UncommentHostsFileLineByHostname set the IsCommented bit for the given hostname to false +func (h *HostsFile) UncommentHostsFileLineByHostname(hostname string) error { + h.Lock() + defer h.Unlock() + + for idx := range h.HostsFileLines { + for _, hn := range h.HostsFileLines[idx].Hostnames { + if hn == hostname { + if h.HostsFileLines[idx].IsCommented { + h.HostsFileLines[idx].IsCommented = false + + h.HostsFileLines[idx].Raw = h.RenderHostsFileLine(idx) + return nil + } + + return ErrAlredyUncommentedLine + } + } + } + + return ErrHostnameNotFound +} + +func (h *HostsFile) UncommentHostsFileLinesByHostname(hostname string) { + h.Lock() + defer h.Unlock() + + for idx := range h.HostsFileLines { + for _, hn := range h.HostsFileLines[idx].Hostnames { + if hn == hostname { + if h.HostsFileLines[idx].IsCommented { + h.HostsFileLines[idx].IsCommented = false + + h.HostsFileLines[idx].Raw = h.RenderHostsFileLine(idx) + } + } + } + } +} + +func (h *HostsFile) UncommentHostsFileLinesByHostnameAsRegexp(hostname string) { + h.Lock() + defer h.Unlock() + + reg := regexp.MustCompile(hostname) + + for idx := range h.HostsFileLines { + for _, hn := range h.HostsFileLines[idx].Hostnames { + if reg.MatchString(hn) { + if h.HostsFileLines[idx].IsCommented { + h.HostsFileLines[idx].IsCommented = false + + h.HostsFileLines[idx].Raw = h.RenderHostsFileLine(idx) + continue + } + } + } + } +} diff --git a/vendor/github.com/areYouLazy/libhosty/parser.go b/vendor/github.com/areYouLazy/libhosty/parser.go new file mode 100644 index 0000000000..9f090d09f6 --- /dev/null +++ b/vendor/github.com/areYouLazy/libhosty/parser.go @@ -0,0 +1,112 @@ +package libhosty + +import ( + "io/ioutil" + "net" + "strings" +) + +//ParseHostsFile parse a hosts file from the given location. +// error is not nil if something goes wrong +func ParseHostsFile(path string) ([]HostsFileLine, error) { + byteData, err := ioutil.ReadFile(path) + if err != nil { + return nil, err + } + + return parser(byteData) +} + +//ParseHostsFileAsString parse a hosts file from a given string. +// error is not nil if something goes wrong +func ParseHostsFileAsString(stringData string) ([]HostsFileLine, error) { + bytesData := []byte(stringData) + return parser(bytesData) +} + +func parser(bytesData []byte) ([]HostsFileLine, error) { + byteDataNormalized := strings.Replace(string(bytesData), "\r\n", "\n", -1) + fileLines := strings.Split(byteDataNormalized, "\n") + hostsFileLines := make([]HostsFileLine, len(fileLines)) + + // trim leading an trailing whitespace + for i, l := range fileLines { + curLine := &hostsFileLines[i] + curLine.Number = i + curLine.Raw = l + + // trim line + curLine.trimed = strings.TrimSpace(l) + + // check if it's an empty line + if curLine.trimed == "" { + curLine.Type = LineTypeEmpty + continue + } + + // check if line starts with a # + if strings.HasPrefix(curLine.trimed, "#") { + // this can be a comment or a commented host line + // so remove the 1st char (#), trim spaces + // and try to parse the line as a host line + noCommentLine := strings.TrimPrefix(curLine.trimed, "#") + tmpParts := strings.Fields(strings.TrimSpace(noCommentLine)) + + // check what we have + switch len(tmpParts) { + case 0: + // empty line, comment line + curLine.Type = LineTypeComment + continue + default: + // non-empty line, try to parse as address + address := net.ParseIP(tmpParts[0]) + + // if address is nil this line is a comment + if address == nil { + curLine.Type = LineTypeComment + continue + } + } + + // otherwise it is a commented line so let's try to parse it as a normal line + curLine.IsCommented = true + curLine.trimed = noCommentLine + } + + // not a comment or empty line so try to parse it + // check if it contains a comment + curLineSplit := strings.SplitN(curLine.trimed, "#", 2) + if len(curLineSplit) > 1 { + // trim spaces from comments + curLine.Comment = strings.TrimSpace(curLineSplit[1]) + } + + curLine.trimed = curLineSplit[0] + curLine.Parts = strings.Fields(curLine.trimed) + + if len(curLine.Parts) > 1 { + // parse address to ensure we have a valid address line + tmpIP := net.ParseIP(curLine.Parts[0]) + if tmpIP != nil { + + curLine.Type = LineTypeAddress + curLine.Address = tmpIP + // lower case all + for _, p := range curLine.Parts[1:] { + curLine.Hostnames = append(curLine.Hostnames, strings.ToLower(p)) + } + + continue + } + } + + // if we can't figure out what this line is mark it as unknown + curLine.Type = LineTypeUnknown + } + + // normalize slice + hostsFileLines = hostsFileLines[:] + + return hostsFileLines, nil +} diff --git a/vendor/github.com/areYouLazy/libhosty/templates.go b/vendor/github.com/areYouLazy/libhosty/templates.go new file mode 100644 index 0000000000..aa0bcacdf0 --- /dev/null +++ b/vendor/github.com/areYouLazy/libhosty/templates.go @@ -0,0 +1,52 @@ +package libhosty + +// linuxHostsTemplate defines default linux hosts file +const linuxHostsTemplate = `# Do not remove the following line, or various programs +# that require network functionality will fail. +127.0.0.1 localhost.localdomain localhost +::1 localhost6.localdomain6 localhost6 +` + +// windowsHostsTemplate defines default windows hosts file +const windowsHostsTemplate = `# Copyright (c) 1993-2006 Microsoft Corp. +# +# This is a sample HOSTS file used by Microsoft TCP/IP for Windows. +# +# This file contains the mappings of IP addresses to host names. Each +# entry should be kept on an individual line. The IP address should +# be placed in the first column followed by the corresponding host name. +# The IP address and the host name should be separated by at least one +# space. +# +# Additionally, comments (such as these) may be inserted on individual +# lines or following the machine name denoted by a '#' symbol. +# +# For example: +# +# 102.54.94.97 rhino.acme.com # source server +# 38.25.63.10 x.acme.com # x client host +# localhost name resolution is handle within DNS itself. +# 127.0.0.1 localhost +# ::1 localhost +` + +// darwinHostsTemplate defines default darwin hosts file +const darwinHostsTemplate = `## +# Host Database +# +# localhost is used to configure the loopback interface +# when the system is booting. Do not change this entry +## +127.0.0.1 localhost +255.255.255.255 broadcasthost::1 localhost + +::1 localhost +fe80::1%lo0 localhost +` + +// dockerDesktopTemplate defines docker desktop hosts entry +const dockerDesktopTemplate = `# Added by Docker Desktop +# To allow the same kube context to work on the host and the container: +127.0.0.1 kubernetes.docker.internal +# End of section +` diff --git a/vendor/github.com/crc-org/admin-helper/pkg/hosts/hosts.go b/vendor/github.com/crc-org/admin-helper/pkg/hosts/hosts.go index 0bfe65513e..e9f2bb847f 100644 --- a/vendor/github.com/crc-org/admin-helper/pkg/hosts/hosts.go +++ b/vendor/github.com/crc-org/admin-helper/pkg/hosts/hosts.go @@ -2,12 +2,14 @@ package hosts import ( "fmt" + "net" "os" "regexp" "sort" "strings" + "sync" - "github.com/goodhosts/hostsfile" + "github.com/areYouLazy/libhosty" ) const ( @@ -15,6 +17,11 @@ const ( dns1123SubdomainRegexp = `[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*` clusterDomain = ".crc.testing" appsDomain = ".apps-crc.testing" + + crcTemplate = `# Added by CRC +# End of CRC section +` + maxHostsInLine = 9 ) var ( @@ -23,20 +30,13 @@ var ( ) type Hosts struct { - File *hostsfile.Hosts + sync.Mutex + File *libhosty.HostsFile HostFilter func(string) bool } -func init() { - // goodhosts unconditionally uses this environment variable - // as an override for the hosts file to use. We don't want admin-helper - // to modify arbitrary file, so we have to unset it before calling into - // goodhosts. - os.Unsetenv("HOSTS_PATH") -} - func New() (*Hosts, error) { - file, err := hostsfile.NewHosts() + file, err := libhosty.Init() if err != nil { return nil, err } @@ -51,34 +51,41 @@ func defaultFilter(s string) bool { return clusterRegexp.MatchString(s) || appRegexp.MatchString(s) } -func (h *Hosts) Add(ip string, hosts []string) error { - if err := h.verifyHosts(hosts); err != nil { - return err - } +func linesContain(lines []*libhosty.HostsFileLine, hostName string) bool { + for _, line := range lines { + for _, hn := range line.Hostnames { + if hn == hostName { + return true + } - if err := h.checkIsWritable(); err != nil { - return err + } } + return false +} + +func uniqueHostnames(lines []*libhosty.HostsFileLine, hosts []string) []string { uniqueHosts := map[string]bool{} - for i := 0; i < len(hosts); i++ { - uniqueHosts[hosts[i]] = true + + // Remove duplicate entries from `hosts` + for _, host := range hosts { + uniqueHosts[host] = true } + // Remove entries in `hosts` which are already present in the file var hostEntries []string - for key := range uniqueHosts { - hostEntries = append(hostEntries, key) + for hostname := range uniqueHosts { + if !linesContain(lines, hostname) { + hostEntries = append(hostEntries, hostname) + } } sort.Strings(hostEntries) - if err := h.File.Add(ip, hostEntries...); err != nil { - return err - } - return h.File.Flush() + return hostEntries } -func (h *Hosts) Remove(hosts []string) error { +func (h *Hosts) Add(ipRaw string, hosts []string) error { if err := h.verifyHosts(hosts); err != nil { return err } @@ -87,65 +94,179 @@ func (h *Hosts) Remove(hosts []string) error { return err } - uniqueHosts := map[string]bool{} - for i := 0; i < len(hosts); i++ { - uniqueHosts[hosts[i]] = true + // parse ip to net.IP + ip := net.ParseIP(ipRaw) + if ip == nil { + return libhosty.ErrCannotParseIPAddress(ipRaw) } - var hostEntries []string - for key := range uniqueHosts { - hostEntries = append(hostEntries, key) + start, end, err := h.verifyCrcSection() + if err != nil { + return err } - for _, host := range hostEntries { - if err := h.File.RemoveByHostname(host); err != nil { - return err - } + lines, err := h.findIP(start, end, ip) + if err != nil { + return err + } + + h.Lock() + defer h.Unlock() + + hostEntries := uniqueHostnames(lines, hosts) + + h.addNewHostEntries(hostEntries, lines, ip) + + return h.File.SaveHostsFile() +} + +func (h *Hosts) addNewHostEntries(hostEntries []string, lines []*libhosty.HostsFileLine, ip net.IP) { + var hostAdder HostAdder + + hostAdder.AppendHosts(hostEntries...) + + for _, line := range lines { + // This will append hosts from the hostAdder to fill the line up to 9 entries + // Lines over 9 entries will be truncated, and their extra + // entries will be added to hostAdder so that they can added to the next lines + hostAdder.FillLine(line) + } + + // Create new lines for entries left-over entries (entries which haven't been added existing lines) + hostsToAdd := hostAdder.PopN(maxHostsInLine) + for len(hostsToAdd) > 0 { + h.createAndAddHostsLine(ip, hostsToAdd, h.lastNonCommentLine()) + hostsToAdd = hostAdder.PopN(maxHostsInLine) } - return h.File.Flush() } -func (h *Hosts) Clean(rawSuffixes []string) error { +func (h *Hosts) lastNonCommentLine() int { + _, end := h.findCrcSection() + return end - 1 +} + +func (h *Hosts) createAndAddHostsLine(ip net.IP, hosts []string, sectionStart int) { + hfl := libhosty.HostsFileLine{ + Type: libhosty.LineTypeAddress, + Address: ip, + Hostnames: hosts, + } + + // inserts to hosts + newHosts := make([]libhosty.HostsFileLine, 0) + newHosts = append(newHosts, h.File.HostsFileLines[:sectionStart+1]...) + newHosts = append(newHosts, hfl) + newLineNum := len(newHosts) - 1 + newHosts = append(newHosts, h.File.HostsFileLines[sectionStart+1:]...) + h.File.HostsFileLines = newHosts + + // generate raw version of the line + hfl.Raw = h.File.RenderHostsFileLine(newLineNum) +} + +func (h *Hosts) Remove(hosts []string) error { + if err := h.verifyHosts(hosts); err != nil { + return err + } + if err := h.checkIsWritable(); err != nil { return err } - var suffixes []string - for _, suffix := range rawSuffixes { - if !strings.HasPrefix(suffix, ".") { - return fmt.Errorf("suffix should start with a dot") - } - suffixes = append(suffixes, suffix) + var hostEntries = make(map[string]struct{}) + for _, key := range hosts { + hostEntries[key] = struct{}{} } - var toDelete []string - for _, line := range h.File.Lines { - for _, host := range line.Hosts { - for _, suffix := range suffixes { - if strings.HasSuffix(host, suffix) { - toDelete = append(toDelete, host) + start, end := h.findCrcSection() + + h.Lock() + defer h.Unlock() + // delete from CRC section + if start > 0 && end > 0 { + for i := end - 1; i >= start; i-- { + line := h.File.GetHostsFileLineByRow(i) + if line.Type == libhosty.LineTypeComment { + continue + } + + for hostIdx := len(line.Hostnames) - 1; hostIdx >= 0; hostIdx-- { + hostname := line.Hostnames[hostIdx] + if _, ok := hostEntries[hostname]; ok { + h.removeHostFromLine(line, hostIdx, i) + } + + } + } + } else { + // CRC section not present, delete hosts from entire file + for _, host := range hosts { + lineIdx, _, err := h.File.LookupByHostname(host) + if err != nil { + continue + } + + line := h.File.GetHostsFileLineByRow(lineIdx) + + for hostIdx, hostname := range line.Hostnames { + if hostname == host { + h.removeHostFromLine(line, hostIdx, lineIdx) break } + } + } } - if err := h.verifyHosts(toDelete); err != nil { + return h.File.SaveHostsFile() +} + +func (h *Hosts) removeHostFromLine(line *libhosty.HostsFileLine, hostIdx int, i int) { + if len(line.Hostnames) >= 1 { + line.Hostnames = append(line.Hostnames[:hostIdx], line.Hostnames[hostIdx+1:]...) + } + + // remove the line if there are no more hostnames (other than the actual one) + if len(line.Hostnames) < 1 { + h.File.RemoveHostsFileLineByRow(i) + } +} + +func (h *Hosts) Clean() error { + if err := h.checkIsWritable(); err != nil { return err } - for _, host := range toDelete { - if err := h.File.RemoveByHostname(host); err != nil { - return err - } + h.Lock() + defer h.Unlock() + + start, end := h.findCrcSection() + // no CRC section present + if start == -1 && end == -1 { + return nil } - return h.File.Flush() + + var newHosts []libhosty.HostsFileLine + + newHosts = append(newHosts, h.File.HostsFileLines[:start-1]...) + newHosts = append(newHosts, h.File.HostsFileLines[end+1:]...) + h.File.HostsFileLines = newHosts + + _, _, emptyLineErr := h.File.AddEmptyFileLine() + if emptyLineErr != nil { + return emptyLineErr + } + + return h.File.SaveHostsFile() } func (h *Hosts) checkIsWritable() error { - if !h.File.IsWritable() { + file, err := os.OpenFile(h.File.Config.FilePath, os.O_WRONLY, 0660) + if err != nil { return fmt.Errorf("host file not writable, try running with elevated privileges") } + defer file.Close() return nil } @@ -154,7 +275,17 @@ func (h *Hosts) Contains(ip, host string) bool { return false } - return h.File.Has(ip, host) + lines := h.File.GetHostsFileLinesByAddress(ip) + + for _, line := range lines { + for _, h := range line.Hostnames { + if h == host { + return true + } + } + } + + return false } func (h *Hosts) verifyHosts(hosts []string) error { @@ -165,3 +296,65 @@ func (h *Hosts) verifyHosts(hosts []string) error { } return nil } + +func (h *Hosts) verifyCrcSection() (int, int, error) { + + start, end := h.findCrcSection() + + if start > 0 && end > 0 { + return start, end, nil + } + + hfl, err := libhosty.ParseHostsFileAsString(crcTemplate) + if err != nil { + return -1, -1, err + } + + h.File.HostsFileLines = append(h.File.HostsFileLines, hfl...) + + start, end = h.findCrcSection() + + if start > 0 && end > 0 { + return start, end, nil + } + + return -1, -1, fmt.Errorf("can't add CRC section, check hosts file") +} + +func (h *Hosts) findCrcSection() (int, int) { + start := -1 + end := -1 + + for i, line := range h.File.HostsFileLines { + if line.Type == libhosty.LineTypeComment { + if strings.Contains(line.Raw, "Added by CRC") { + start = i + continue + } + + if strings.Contains(line.Raw, "End of CRC section") { + end = i + break + } + + } + } + + return start, end +} + +func (h *Hosts) findIP(start, end int, ip net.IP) ([]*libhosty.HostsFileLine, error) { + var result []*libhosty.HostsFileLine + for i := start; i < end; i++ { + line := h.File.GetHostsFileLineByRow(i) + if line.Type == libhosty.LineTypeComment { + continue + } + + if net.IP.Equal(line.Address, ip) { + result = append(result, line) + } + } + + return result, nil +} diff --git a/vendor/github.com/crc-org/admin-helper/pkg/hosts/util.go b/vendor/github.com/crc-org/admin-helper/pkg/hosts/util.go new file mode 100644 index 0000000000..167534f7a4 --- /dev/null +++ b/vendor/github.com/crc-org/admin-helper/pkg/hosts/util.go @@ -0,0 +1,52 @@ +package hosts + +import ( + "github.com/areYouLazy/libhosty" +) + +type HostAdder struct { + hostsToAdd []string +} + +func (adder *HostAdder) PrependHosts(hosts []string) { + adder.hostsToAdd = append(hosts, adder.hostsToAdd...) +} + +func (adder *HostAdder) AppendHosts(hosts ...string) { + adder.hostsToAdd = append(adder.hostsToAdd, hosts...) +} + +func (adder *HostAdder) AppendHost(host string) { + adder.hostsToAdd = append(adder.hostsToAdd, host) +} + +func (adder *HostAdder) Len() int { + return len(adder.hostsToAdd) +} + +func (adder *HostAdder) PopN(count int) []string { + if adder.Len() == 0 { + return []string{} + } + if adder.Len() < count { + count = adder.Len() + } + hosts := adder.hostsToAdd[:count] + adder.hostsToAdd = adder.hostsToAdd[count:] + + return hosts +} + +func (adder *HostAdder) FillLine(line *libhosty.HostsFileLine) { + if len(line.Hostnames) == maxHostsInLine { + return + } + if len(line.Hostnames) > maxHostsInLine { + adder.PrependHosts(line.Hostnames[maxHostsInLine:]) + line.Hostnames = line.Hostnames[0:maxHostsInLine] + return + } + + newHosts := adder.PopN(maxHostsInLine - len(line.Hostnames)) + line.Hostnames = append(line.Hostnames, newHosts...) +} diff --git a/vendor/github.com/dimchansky/utfbom/.gitignore b/vendor/github.com/dimchansky/utfbom/.gitignore deleted file mode 100644 index d7ec5cebb9..0000000000 --- a/vendor/github.com/dimchansky/utfbom/.gitignore +++ /dev/null @@ -1,37 +0,0 @@ -# Binaries for programs and plugins -*.exe -*.dll -*.so -*.dylib -*.o -*.a - -# Folders -_obj -_test - -# Architecture specific extensions/prefixes -*.[568vq] -[568vq].out - -*.cgo1.go -*.cgo2.c -_cgo_defun.c -_cgo_gotypes.go -_cgo_export.* - -_testmain.go - -*.prof - -# Test binary, build with `go test -c` -*.test - -# Output of the go coverage tool, specifically when used with LiteIDE -*.out - -# Project-local glide cache, RE: https://github.com/Masterminds/glide/issues/736 -.glide/ - -# Gogland -.idea/ \ No newline at end of file diff --git a/vendor/github.com/dimchansky/utfbom/.travis.yml b/vendor/github.com/dimchansky/utfbom/.travis.yml deleted file mode 100644 index 19312ee35f..0000000000 --- a/vendor/github.com/dimchansky/utfbom/.travis.yml +++ /dev/null @@ -1,29 +0,0 @@ -language: go -sudo: false - -go: - - 1.10.x - - 1.11.x - - 1.12.x - - 1.13.x - - 1.14.x - - 1.15.x - -cache: - directories: - - $HOME/.cache/go-build - - $HOME/gopath/pkg/mod - -env: - global: - - GO111MODULE=on - -before_install: - - go get github.com/mattn/goveralls - - go get golang.org/x/tools/cmd/cover - - go get golang.org/x/tools/cmd/goimports - - go get golang.org/x/lint/golint -script: - - gofiles=$(find ./ -name '*.go') && [ -z "$gofiles" ] || unformatted=$(goimports -l $gofiles) && [ -z "$unformatted" ] || (echo >&2 "Go files must be formatted with gofmt. Following files has problem:\n $unformatted" && false) - - golint ./... # This won't break the build, just show warnings - - $HOME/gopath/bin/goveralls -service=travis-ci diff --git a/vendor/github.com/dimchansky/utfbom/README.md b/vendor/github.com/dimchansky/utfbom/README.md deleted file mode 100644 index 8ece280089..0000000000 --- a/vendor/github.com/dimchansky/utfbom/README.md +++ /dev/null @@ -1,66 +0,0 @@ -# utfbom [![Godoc](https://godoc.org/github.com/dimchansky/utfbom?status.png)](https://godoc.org/github.com/dimchansky/utfbom) [![License](https://img.shields.io/:license-apache-blue.svg)](https://opensource.org/licenses/Apache-2.0) [![Build Status](https://travis-ci.org/dimchansky/utfbom.svg?branch=master)](https://travis-ci.org/dimchansky/utfbom) [![Go Report Card](https://goreportcard.com/badge/github.com/dimchansky/utfbom)](https://goreportcard.com/report/github.com/dimchansky/utfbom) [![Coverage Status](https://coveralls.io/repos/github/dimchansky/utfbom/badge.svg?branch=master)](https://coveralls.io/github/dimchansky/utfbom?branch=master) - -The package utfbom implements the detection of the BOM (Unicode Byte Order Mark) and removing as necessary. It can also return the encoding detected by the BOM. - -## Installation - - go get -u github.com/dimchansky/utfbom - -## Example - -```go -package main - -import ( - "bytes" - "fmt" - "io/ioutil" - - "github.com/dimchansky/utfbom" -) - -func main() { - trySkip([]byte("\xEF\xBB\xBFhello")) - trySkip([]byte("hello")) -} - -func trySkip(byteData []byte) { - fmt.Println("Input:", byteData) - - // just skip BOM - output, err := ioutil.ReadAll(utfbom.SkipOnly(bytes.NewReader(byteData))) - if err != nil { - fmt.Println(err) - return - } - fmt.Println("ReadAll with BOM skipping", output) - - // skip BOM and detect encoding - sr, enc := utfbom.Skip(bytes.NewReader(byteData)) - fmt.Printf("Detected encoding: %s\n", enc) - output, err = ioutil.ReadAll(sr) - if err != nil { - fmt.Println(err) - return - } - fmt.Println("ReadAll with BOM detection and skipping", output) - fmt.Println() -} -``` - -Output: - -``` -$ go run main.go -Input: [239 187 191 104 101 108 108 111] -ReadAll with BOM skipping [104 101 108 108 111] -Detected encoding: UTF8 -ReadAll with BOM detection and skipping [104 101 108 108 111] - -Input: [104 101 108 108 111] -ReadAll with BOM skipping [104 101 108 108 111] -Detected encoding: Unknown -ReadAll with BOM detection and skipping [104 101 108 108 111] -``` - - diff --git a/vendor/github.com/dimchansky/utfbom/utfbom.go b/vendor/github.com/dimchansky/utfbom/utfbom.go deleted file mode 100644 index 77a303e564..0000000000 --- a/vendor/github.com/dimchansky/utfbom/utfbom.go +++ /dev/null @@ -1,192 +0,0 @@ -// Package utfbom implements the detection of the BOM (Unicode Byte Order Mark) and removing as necessary. -// It wraps an io.Reader object, creating another object (Reader) that also implements the io.Reader -// interface but provides automatic BOM checking and removing as necessary. -package utfbom - -import ( - "errors" - "io" -) - -// Encoding is type alias for detected UTF encoding. -type Encoding int - -// Constants to identify detected UTF encodings. -const ( - // Unknown encoding, returned when no BOM was detected - Unknown Encoding = iota - - // UTF8, BOM bytes: EF BB BF - UTF8 - - // UTF-16, big-endian, BOM bytes: FE FF - UTF16BigEndian - - // UTF-16, little-endian, BOM bytes: FF FE - UTF16LittleEndian - - // UTF-32, big-endian, BOM bytes: 00 00 FE FF - UTF32BigEndian - - // UTF-32, little-endian, BOM bytes: FF FE 00 00 - UTF32LittleEndian -) - -// String returns a user-friendly string representation of the encoding. Satisfies fmt.Stringer interface. -func (e Encoding) String() string { - switch e { - case UTF8: - return "UTF8" - case UTF16BigEndian: - return "UTF16BigEndian" - case UTF16LittleEndian: - return "UTF16LittleEndian" - case UTF32BigEndian: - return "UTF32BigEndian" - case UTF32LittleEndian: - return "UTF32LittleEndian" - default: - return "Unknown" - } -} - -const maxConsecutiveEmptyReads = 100 - -// Skip creates Reader which automatically detects BOM (Unicode Byte Order Mark) and removes it as necessary. -// It also returns the encoding detected by the BOM. -// If the detected encoding is not needed, you can call the SkipOnly function. -func Skip(rd io.Reader) (*Reader, Encoding) { - // Is it already a Reader? - b, ok := rd.(*Reader) - if ok { - return b, Unknown - } - - enc, left, err := detectUtf(rd) - return &Reader{ - rd: rd, - buf: left, - err: err, - }, enc -} - -// SkipOnly creates Reader which automatically detects BOM (Unicode Byte Order Mark) and removes it as necessary. -func SkipOnly(rd io.Reader) *Reader { - r, _ := Skip(rd) - return r -} - -// Reader implements automatic BOM (Unicode Byte Order Mark) checking and -// removing as necessary for an io.Reader object. -type Reader struct { - rd io.Reader // reader provided by the client - buf []byte // buffered data - err error // last error -} - -// Read is an implementation of io.Reader interface. -// The bytes are taken from the underlying Reader, but it checks for BOMs, removing them as necessary. -func (r *Reader) Read(p []byte) (n int, err error) { - if len(p) == 0 { - return 0, nil - } - - if r.buf == nil { - if r.err != nil { - return 0, r.readErr() - } - - return r.rd.Read(p) - } - - // copy as much as we can - n = copy(p, r.buf) - r.buf = nilIfEmpty(r.buf[n:]) - return n, nil -} - -func (r *Reader) readErr() error { - err := r.err - r.err = nil - return err -} - -var errNegativeRead = errors.New("utfbom: reader returned negative count from Read") - -func detectUtf(rd io.Reader) (enc Encoding, buf []byte, err error) { - buf, err = readBOM(rd) - - if len(buf) >= 4 { - if isUTF32BigEndianBOM4(buf) { - return UTF32BigEndian, nilIfEmpty(buf[4:]), err - } - if isUTF32LittleEndianBOM4(buf) { - return UTF32LittleEndian, nilIfEmpty(buf[4:]), err - } - } - - if len(buf) > 2 && isUTF8BOM3(buf) { - return UTF8, nilIfEmpty(buf[3:]), err - } - - if (err != nil && err != io.EOF) || (len(buf) < 2) { - return Unknown, nilIfEmpty(buf), err - } - - if isUTF16BigEndianBOM2(buf) { - return UTF16BigEndian, nilIfEmpty(buf[2:]), err - } - if isUTF16LittleEndianBOM2(buf) { - return UTF16LittleEndian, nilIfEmpty(buf[2:]), err - } - - return Unknown, nilIfEmpty(buf), err -} - -func readBOM(rd io.Reader) (buf []byte, err error) { - const maxBOMSize = 4 - var bom [maxBOMSize]byte // used to read BOM - - // read as many bytes as possible - for nEmpty, n := 0, 0; err == nil && len(buf) < maxBOMSize; buf = bom[:len(buf)+n] { - if n, err = rd.Read(bom[len(buf):]); n < 0 { - panic(errNegativeRead) - } - if n > 0 { - nEmpty = 0 - } else { - nEmpty++ - if nEmpty >= maxConsecutiveEmptyReads { - err = io.ErrNoProgress - } - } - } - return -} - -func isUTF32BigEndianBOM4(buf []byte) bool { - return buf[0] == 0x00 && buf[1] == 0x00 && buf[2] == 0xFE && buf[3] == 0xFF -} - -func isUTF32LittleEndianBOM4(buf []byte) bool { - return buf[0] == 0xFF && buf[1] == 0xFE && buf[2] == 0x00 && buf[3] == 0x00 -} - -func isUTF8BOM3(buf []byte) bool { - return buf[0] == 0xEF && buf[1] == 0xBB && buf[2] == 0xBF -} - -func isUTF16BigEndianBOM2(buf []byte) bool { - return buf[0] == 0xFE && buf[1] == 0xFF -} - -func isUTF16LittleEndianBOM2(buf []byte) bool { - return buf[0] == 0xFF && buf[1] == 0xFE -} - -func nilIfEmpty(buf []byte) (res []byte) { - if len(buf) > 0 { - res = buf - } - return -} diff --git a/vendor/github.com/goodhosts/hostsfile/.gitignore b/vendor/github.com/goodhosts/hostsfile/.gitignore deleted file mode 100644 index 723ef36f4e..0000000000 --- a/vendor/github.com/goodhosts/hostsfile/.gitignore +++ /dev/null @@ -1 +0,0 @@ -.idea \ No newline at end of file diff --git a/vendor/github.com/goodhosts/hostsfile/LICENSE b/vendor/github.com/goodhosts/hostsfile/LICENSE deleted file mode 100644 index d9a10c0d8e..0000000000 --- a/vendor/github.com/goodhosts/hostsfile/LICENSE +++ /dev/null @@ -1,176 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS diff --git a/vendor/github.com/goodhosts/hostsfile/Makefile b/vendor/github.com/goodhosts/hostsfile/Makefile deleted file mode 100644 index 74b429609e..0000000000 --- a/vendor/github.com/goodhosts/hostsfile/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -ci: - @goimports -l . || (goimports -d . && exit 1) - @golangci-lint run - @go test -v . -.DEFAULT_GOAL := ci \ No newline at end of file diff --git a/vendor/github.com/goodhosts/hostsfile/hosts.go b/vendor/github.com/goodhosts/hostsfile/hosts.go deleted file mode 100644 index dfda77aea6..0000000000 --- a/vendor/github.com/goodhosts/hostsfile/hosts.go +++ /dev/null @@ -1,451 +0,0 @@ -package hostsfile - -import ( - "bufio" - "bytes" - "fmt" - "net" - "os" - "path/filepath" - "sort" - "sync" - - "github.com/asaskevich/govalidator" - "github.com/dimchansky/utfbom" -) - -type lookup struct { - sync.RWMutex - l map[string][]int -} - -type Hosts struct { - Path string - Lines []HostsLine - ips lookup - hosts lookup -} - -// NewHosts return a new instance of ``Hosts`` using the default hosts file path. -func NewHosts() (*Hosts, error) { - osHostsFilePath := os.ExpandEnv(filepath.FromSlash(HostsFilePath)) - - if env, isset := os.LookupEnv("HOSTS_PATH"); isset && len(env) > 0 { - osHostsFilePath = os.ExpandEnv(filepath.FromSlash(env)) - } - - return NewCustomHosts(osHostsFilePath) -} - -// NewCustomHosts return a new instance of ``Hosts`` using a custom hosts file path. -func NewCustomHosts(osHostsFilePath string) (*Hosts, error) { - hosts := &Hosts{ - Path: osHostsFilePath, - ips: lookup{l: make(map[string][]int)}, - hosts: lookup{l: make(map[string][]int)}, - } - - if err := hosts.Load(); err != nil { - return hosts, err - } - - return hosts, nil -} - -// IsWritable return ```true``` if hosts file is writable. -func (h *Hosts) IsWritable() bool { - file, err := os.OpenFile(h.Path, os.O_WRONLY, 0660) - if err != nil { - return false - } - defer file.Close() - return true -} - -// Load the hosts file into ```l.Lines```. -// ```Load()``` is called by ```NewHosts()``` and ```Hosts.Flush()``` so you -// generally you won't need to call this yourself. -func (h *Hosts) Load() error { - file, err := os.Open(h.Path) - if err != nil { - return err - } - defer file.Close() - - // if you're reloading from disk confirm you refresh the hash maps and lines - if len(h.Lines) != 0 { - h.ips = lookup{l: make(map[string][]int)} - h.hosts = lookup{l: make(map[string][]int)} - h.Lines = []HostsLine{} - } - - scanner := bufio.NewScanner(utfbom.SkipOnly(file)) - for scanner.Scan() { - hl := NewHostsLine(scanner.Text()) - h.Lines = append(h.Lines, hl) - pos := len(h.Lines) - 1 - h.addIpPosition(hl.IP, pos) - for _, host := range hl.Hosts { - h.addHostPositions(host, pos) - } - } - - return scanner.Err() -} - -// Flush any changes made to hosts file. -func (h *Hosts) Flush() error { - h.preFlushClean() - file, err := os.Create(h.Path) - if err != nil { - return err - } - - defer file.Close() - - w := bufio.NewWriter(file) - for _, line := range h.Lines { - if _, err := fmt.Fprintf(w, "%s%s", line.ToRaw(), eol); err != nil { - return err - } - } - - err = w.Flush() - if err != nil { - return err - } - - return h.Load() -} - -// AddRaw takes a line from a hosts file and parses/adds the HostsLine -func (h *Hosts) AddRaw(raw ...string) error { - for _, r := range raw { - nl := NewHostsLine(r) - if nl.IP != "" && net.ParseIP(nl.IP) == nil { - return fmt.Errorf("%q is an invalid IP address", nl.IP) - } - - for _, host := range nl.Hosts { - if !govalidator.IsDNSName(host) { - return fmt.Errorf("hostname is not a valid dns name: %s", host) - } - } - - h.Lines = append(h.Lines, nl) - pos := len(h.Lines) - 1 - h.addIpPosition(nl.IP, pos) - for _, host := range nl.Hosts { - h.addHostPositions(host, pos) - } - } - - return nil -} - -// Add an entry to the hosts file. -func (h *Hosts) Add(ip string, hosts ...string) error { - if net.ParseIP(ip) == nil { - return fmt.Errorf("%q is an invalid IP address", ip) - } - - position := h.getIpPositions(ip) - if len(position) == 0 { - nl := HostsLine{ - Raw: buildRawLine(ip, hosts), - IP: ip, - Hosts: hosts, - } - h.Lines = append(h.Lines, nl) - pos := len(h.Lines) - 1 - h.addIpPosition(ip, pos) - for _, host := range nl.Hosts { - h.addHostPositions(host, pos) - } - } else { - // add new host to the first one we find - hostsCopy := h.Lines[position[0]].Hosts - for _, addHost := range hosts { - if h.Has(ip, addHost) { - // this combo already exists - continue - } - - if !govalidator.IsDNSName(addHost) { - return fmt.Errorf("hostname is not a valid dns name: %s", addHost) - } - if itemInSliceString(addHost, hostsCopy) { - continue // host exists for ip already - } - - hostsCopy = append(hostsCopy, addHost) - h.addHostPositions(addHost, position[0]) - } - h.Lines[position[0]].Hosts = hostsCopy - h.Lines[position[0]].Raw = h.Lines[position[0]].ToRaw() // reset raw - } - - return nil -} - -func (h *Hosts) Clear() { - h.Lines = []HostsLine{} -} - -// Clean merge duplicate ips and hosts per ip -func (h *Hosts) Clean() { - h.RemoveDuplicateIps() - h.RemoveDuplicateHosts() - h.SortHosts() - h.SortByIp() - h.HostsPerLine(HostsPerLine) -} - -// Has return a bool if ip/host combo in hosts file. -func (h *Hosts) Has(ip string, host string) bool { - ippos := h.getIpPositions(ip) - hostpos := h.getHostPositions(host) - for _, pos := range ippos { - if itemInSliceInt(pos, hostpos) { - // if ip and host have matching lookup positions we have a combo match - return true - } - } - - return false -} - -// HasHostname return a bool if hostname in hosts file. -func (h *Hosts) HasHostname(host string) bool { - return len(h.getHostPositions(host)) > 0 -} - -func (h *Hosts) HasIp(ip string) bool { - return len(h.getIpPositions(ip)) > 0 -} - -// Remove an entry from the hosts file. -func (h *Hosts) Remove(ip string, hosts ...string) error { - var outputLines []HostsLine - if net.ParseIP(ip) == nil { - return fmt.Errorf("%q is an invalid IP address", ip) - } - - for _, line := range h.Lines { - // Bad lines or comments just get readded. - if line.Err != nil || line.IsComment() || line.IP != ip { - outputLines = append(outputLines, line) - continue - } - - var newHosts []string - for _, checkHost := range line.Hosts { - if !itemInSliceString(checkHost, hosts) { - newHosts = append(newHosts, checkHost) - } - } - - // If hosts is empty, skip the line completely. - if len(newHosts) > 0 { - newLineRaw := line.IP - - for _, host := range newHosts { - newLineRaw = fmt.Sprintf("%s %s", newLineRaw, host) - } - newLine := NewHostsLine(newLineRaw) - outputLines = append(outputLines, newLine) - } - } - - h.Lines = outputLines - return nil -} - -// RemoveByHostname remove entries by hostname from the hosts file. -func (h *Hosts) RemoveByHostname(host string) error { - for _, p := range h.getHostPositions(host) { - line := &h.Lines[p] - if len(line.Hosts) > 0 { - line.Hosts = removeFromSliceString(host, line.Hosts) - line.RegenRaw() - } - h.removeHostPositions(host, p) - } - - return nil -} - -func (h *Hosts) RemoveByIp(ip string) error { - pos := h.getIpPositions(ip) - for len(pos) > 0 { - for _, p := range pos { - h.removeByPosition(p) - } - } - - return nil -} - -func (h *Hosts) RemoveDuplicateIps() { - ipCount := make(map[string]int) - for _, line := range h.Lines { - ipCount[line.IP]++ - } - for ip, count := range ipCount { - if count > 1 { - h.combineIp(ip) - } - } -} - -func (h *Hosts) RemoveDuplicateHosts() { - for pos, line := range h.Lines { - line.RemoveDuplicateHosts() - h.Lines[pos] = line - } -} - -func (h *Hosts) SortHosts() { - for pos, line := range h.Lines { - line.SortHosts() - h.Lines[pos] = line - } -} - -// SortByIp convert to net.IP and byte.Compare -func (h *Hosts) SortByIp() { - sortedIps := make([]net.IP, 0, len(h.Lines)) - for _, l := range h.Lines { - sortedIps = append(sortedIps, net.ParseIP(l.IP)) - } - sort.Slice(sortedIps, func(i, j int) bool { - return bytes.Compare(sortedIps[i], sortedIps[j]) < 0 - }) - - var sortedLines []HostsLine - for _, ip := range sortedIps { - for _, l := range h.Lines { - if ip.String() == l.IP { - sortedLines = append(sortedLines, l) - } - } - } - h.Lines = sortedLines -} - -func (h *Hosts) HostsPerLine(count int) { - // restacks everything into 1 ip again so we can do the split, do this even if count is -1 so it can reset the slice - h.RemoveDuplicateIps() - if count <= 0 { - return - } - var newLines []HostsLine - for _, line := range h.Lines { - if len(line.Hosts) <= count { - newLines = append(newLines, line) - continue - } - - for i := 0; i < len(line.Hosts); i += count { - lineCopy := line - end := len(line.Hosts) - if end > i+count { - end = i + count - } - - lineCopy.Hosts = line.Hosts[i:end] - lineCopy.Raw = lineCopy.ToRaw() - newLines = append(newLines, lineCopy) - } - } - h.Lines = newLines -} - -func (h *Hosts) combineIp(ip string) { - newLine := HostsLine{ - IP: ip, - } - - linesCopy := make([]HostsLine, len(h.Lines)) - copy(linesCopy, h.Lines) - for _, line := range linesCopy { - if line.IP == ip { - newLine.Combine(line) - } - } - newLine.SortHosts() - h.removeIp(ip) - h.Lines = append(h.Lines, newLine) -} - -func (h *Hosts) removeByPosition(pos int) { - if pos == 0 && len(h.Lines) == 1 { - h.Clear() - return - } - if pos == len(h.Lines) { - h.Lines = h.Lines[:pos-1] - return - } - h.Lines = append(h.Lines[:pos], h.Lines[pos+1:]...) -} - -func (h *Hosts) removeIp(ip string) { - var newLines []HostsLine - for _, line := range h.Lines { - if line.IP != ip { - newLines = append(newLines, line) - } - } - - h.Lines = newLines -} - -func (h *Hosts) getHostPositions(host string) []int { - h.hosts.RLock() - defer h.hosts.RUnlock() - i, ok := h.hosts.l[host] - if ok { - return i - } - return []int{} -} - -func (h *Hosts) addHostPositions(host string, pos int) { - h.hosts.Lock() - defer h.hosts.Unlock() - h.hosts.l[host] = append(h.hosts.l[host], pos) -} - -func (h *Hosts) removeHostPositions(host string, pos int) { - h.hosts.Lock() - defer h.hosts.Unlock() - positions := h.hosts.l[host] - h.hosts.l[host] = removeFromSliceInt(pos, positions) -} - -func (h *Hosts) getIpPositions(ip string) []int { - h.ips.RLock() - defer h.ips.RUnlock() - i, ok := h.ips.l[ip] - if ok { - return i - } - - return []int{} -} - -func (h *Hosts) addIpPosition(ip string, pos int) { - h.ips.Lock() - defer h.ips.Unlock() - h.ips.l[ip] = append(h.ips.l[ip], pos) -} - -func buildRawLine(ip string, hosts []string) string { - output := ip - for _, host := range hosts { - output = fmt.Sprintf("%s %s", output, host) - } - - return output -} diff --git a/vendor/github.com/goodhosts/hostsfile/hostsline.go b/vendor/github.com/goodhosts/hostsfile/hostsline.go deleted file mode 100644 index aa9f26fb5c..0000000000 --- a/vendor/github.com/goodhosts/hostsfile/hostsline.go +++ /dev/null @@ -1,108 +0,0 @@ -package hostsfile - -import ( - "fmt" - "net" - "sort" - "strings" -) - -type HostsLine struct { - IP string - Hosts []string - Raw string - Err error - Comment string -} - -const commentChar string = "#" - -// NewHostsLine return a new instance of ```HostsLine```. -func NewHostsLine(raw string) HostsLine { - output := HostsLine{Raw: raw} - if output.IsComment() { //whole line is comment - return output - } - - if output.HasComment() { //trailing comment - commentSplit := strings.Split(output.Raw, commentChar) - raw = commentSplit[0] - output.Comment = commentSplit[1] - } - - fields := strings.Fields(raw) - if len(fields) == 0 { - return output - } - - rawIP := fields[0] - if net.ParseIP(rawIP) == nil { - output.Err = fmt.Errorf("bad hosts line: %q", raw) - } - - output.IP = rawIP - output.Hosts = fields[1:] - - return output -} - -func (l *HostsLine) ToRaw() string { - var comment string - if l.IsComment() { //Whole line is comment - return l.Raw - } - - if l.Comment != "" { - comment = fmt.Sprintf(" %s%s", commentChar, l.Comment) - } - - return fmt.Sprintf("%s %s%s", l.IP, strings.Join(l.Hosts, " "), comment) -} - -func (l *HostsLine) RemoveDuplicateHosts() { - unique := make(map[string]struct{}) - for _, h := range l.Hosts { - unique[h] = struct{}{} - } - - l.Hosts = []string{} - for k := range unique { - l.Hosts = append(l.Hosts, k) - } - l.Raw = l.ToRaw() -} - -func (l *HostsLine) Combine(hostline HostsLine) { - l.Hosts = append(l.Hosts, hostline.Hosts...) - if l.Comment == "" { - l.Comment = hostline.Comment - } else { - l.Comment = fmt.Sprintf("%s %s", l.Comment, hostline.Comment) - } - l.Raw = l.ToRaw() -} - -func (l *HostsLine) SortHosts() { - sort.Strings(l.Hosts) - l.Raw = l.ToRaw() -} - -func (l *HostsLine) IsComment() bool { - return strings.HasPrefix(strings.TrimSpace(l.Raw), commentChar) -} - -func (l *HostsLine) HasComment() bool { - return strings.Contains(l.Raw, commentChar) -} - -func (l *HostsLine) IsValid() bool { - return l.IP != "" -} - -func (l *HostsLine) IsMalformed() bool { - return l.Err != nil -} - -func (l *HostsLine) RegenRaw() { - l.Raw = fmt.Sprintf("%s %s", l.IP, strings.Join(l.Hosts, " ")) -} diff --git a/vendor/github.com/goodhosts/hostsfile/make.bat b/vendor/github.com/goodhosts/hostsfile/make.bat deleted file mode 100644 index c4f7566182..0000000000 --- a/vendor/github.com/goodhosts/hostsfile/make.bat +++ /dev/null @@ -1,27 +0,0 @@ -@echo off -SETLOCAL ENABLEDELAYEDEXPANSION -set LF=^ - -echo %1% -if "%1%"=="" ( - set cmd=ci -) else ( - set cmd=%1% -) - -if "%cmd%" == "ci" ( - for /F %%i in ('goimports -l .') do ( - set "line=%%i" - set goimports=%goimports%!line!!LF! - ) - - if not "!goimports!" == "" ( - goimports -d . - goto :eof - ) - - golangci-lint run || goto :eof - go test -v . || goto :eof - - goto :eof -) diff --git a/vendor/github.com/goodhosts/hostsfile/slice.go b/vendor/github.com/goodhosts/hostsfile/slice.go deleted file mode 100644 index aace3e8450..0000000000 --- a/vendor/github.com/goodhosts/hostsfile/slice.go +++ /dev/null @@ -1,55 +0,0 @@ -package hostsfile - -func itemInSliceString(item string, list []string) bool { - for _, i := range list { - if i == item { - return true - } - } - return false -} - -func itemInSliceInt(item int, list []int) bool { - for _, i := range list { - if i == item { - return true - } - } - return false -} - -func removeFromSliceString(s string, slice []string) []string { - pos := findPositionInSliceString(s, slice) - for pos > -1 { - slice = append(slice[:pos], slice[pos+1:]...) - pos = findPositionInSliceString(s, slice) - } - return slice -} - -func findPositionInSliceString(s string, slice []string) int { - for index, v := range slice { - if v == s { - return index - } - } - return -1 -} - -func removeFromSliceInt(s int, slice []int) []int { - pos := findPositionInSliceInt(s, slice) - for pos > -1 { - slice = append(slice[:pos], slice[pos+1:]...) - pos = findPositionInSliceInt(s, slice) - } - return slice -} - -func findPositionInSliceInt(s int, slice []int) int { - for index, v := range slice { - if v == s { - return index - } - } - return -1 -} diff --git a/vendor/github.com/goodhosts/hostsfile/utils.go b/vendor/github.com/goodhosts/hostsfile/utils.go deleted file mode 100644 index 46cc58c47a..0000000000 --- a/vendor/github.com/goodhosts/hostsfile/utils.go +++ /dev/null @@ -1,12 +0,0 @@ -//go:build !windows -//+build !windows - -package hostsfile - -var ( - HostsPerLine = -1 // unlimited - HostsFilePath = "/etc/hosts" - eol = "\n" -) - -func (h *Hosts) preFlushClean() {} // no op diff --git a/vendor/github.com/goodhosts/hostsfile/utils_windows.go b/vendor/github.com/goodhosts/hostsfile/utils_windows.go deleted file mode 100644 index 43e32081a9..0000000000 --- a/vendor/github.com/goodhosts/hostsfile/utils_windows.go +++ /dev/null @@ -1,12 +0,0 @@ -package hostsfile - -var ( - HostsPerLine = 9 - HostsFilePath = "${SystemRoot}/System32/drivers/etc/hosts" - eol = "\r\n" -) - -func (h *Hosts) preFlushClean() { - // need to force hosts per line always on windows see https://github.com/goodhosts/hostsfile/issues/18 - h.HostsPerLine(HostsPerLine) -} diff --git a/vendor/modules.txt b/vendor/modules.txt index 701cb01c1c..d3f5c8f53a 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -59,6 +59,9 @@ github.com/alessio/shellescape # github.com/apparentlymart/go-cidr v1.1.0 ## explicit github.com/apparentlymart/go-cidr/cidr +# github.com/areYouLazy/libhosty v1.1.0 +## explicit; go 1.16 +github.com/areYouLazy/libhosty # github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 ## explicit; go 1.13 github.com/asaskevich/govalidator @@ -188,8 +191,8 @@ github.com/containers/storage/pkg/unshare ## explicit; go 1.12 github.com/coreos/go-systemd/v22/activation github.com/coreos/go-systemd/v22/daemon -# github.com/crc-org/admin-helper v0.0.12 -## explicit; go 1.17 +# github.com/crc-org/admin-helper v0.5.2 +## explicit; go 1.20 github.com/crc-org/admin-helper/pkg/client github.com/crc-org/admin-helper/pkg/hosts github.com/crc-org/admin-helper/pkg/types @@ -238,9 +241,6 @@ github.com/danieljoos/wincred # github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc ## explicit github.com/davecgh/go-spew/spew -# github.com/dimchansky/utfbom v1.1.1 -## explicit -github.com/dimchansky/utfbom # github.com/distribution/reference v0.5.0 ## explicit; go 1.20 github.com/distribution/reference @@ -349,9 +349,6 @@ github.com/golang/protobuf/ptypes github.com/golang/protobuf/ptypes/any github.com/golang/protobuf/ptypes/duration github.com/golang/protobuf/ptypes/timestamp -# github.com/goodhosts/hostsfile v0.1.1 -## explicit; go 1.17 -github.com/goodhosts/hostsfile # github.com/google/btree v1.1.2 ## explicit; go 1.18 github.com/google/btree