Răsfoiți Sursa

Add integration tests for feed creation

Frédéric Guillot 8 ani în urmă
părinte
comite
39b03cc393
46 a modificat fișierele cu 859 adăugiri și 36 ștergeri
  1. 5 5
      Gopkg.lock
  2. 4 0
      Gopkg.toml
  3. 3 1
      README.md
  4. 71 3
      integration_test.go
  5. 6 1
      server/api/controller/feed.go
  6. 0 1
      storage/feed.go
  7. 4 3
      storage/icon.go
  8. 1 1
      vendor/github.com/miniflux/miniflux-go/README.md
  9. 10 6
      vendor/github.com/miniflux/miniflux-go/client.go
  10. 3 8
      vendor/golang.org/x/crypto/ssh/terminal/util_windows.go
  11. 7 0
      vendor/golang.org/x/net/http/httpproxy/export_test.go
  12. 239 0
      vendor/golang.org/x/net/http/httpproxy/proxy.go
  13. 298 0
      vendor/golang.org/x/net/http/httpproxy/proxy_test.go
  14. 1 0
      vendor/golang.org/x/sys/unix/linux/types.go
  15. 0 6
      vendor/golang.org/x/sys/unix/mkall.sh
  16. 0 1
      vendor/golang.org/x/sys/unix/syscall_linux.go
  17. 1 0
      vendor/golang.org/x/sys/unix/syscall_linux_386.go
  18. 1 0
      vendor/golang.org/x/sys/unix/syscall_linux_amd64.go
  19. 1 0
      vendor/golang.org/x/sys/unix/syscall_linux_arm.go
  20. 1 0
      vendor/golang.org/x/sys/unix/syscall_linux_mips64x.go
  21. 1 0
      vendor/golang.org/x/sys/unix/syscall_linux_mipsx.go
  22. 1 0
      vendor/golang.org/x/sys/unix/syscall_linux_ppc64x.go
  23. 1 0
      vendor/golang.org/x/sys/unix/syscall_linux_s390x.go
  24. 1 0
      vendor/golang.org/x/sys/unix/syscall_linux_sparc64.go
  25. 38 0
      vendor/golang.org/x/sys/unix/syscall_linux_test.go
  26. 15 0
      vendor/golang.org/x/sys/unix/zsyscall_linux_386.go
  27. 15 0
      vendor/golang.org/x/sys/unix/zsyscall_linux_amd64.go
  28. 15 0
      vendor/golang.org/x/sys/unix/zsyscall_linux_arm.go
  29. 15 0
      vendor/golang.org/x/sys/unix/zsyscall_linux_mips.go
  30. 15 0
      vendor/golang.org/x/sys/unix/zsyscall_linux_mips64.go
  31. 15 0
      vendor/golang.org/x/sys/unix/zsyscall_linux_mips64le.go
  32. 15 0
      vendor/golang.org/x/sys/unix/zsyscall_linux_mipsle.go
  33. 15 0
      vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64.go
  34. 15 0
      vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64le.go
  35. 15 0
      vendor/golang.org/x/sys/unix/zsyscall_linux_s390x.go
  36. 1 0
      vendor/golang.org/x/sys/unix/ztypes_linux_386.go
  37. 1 0
      vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go
  38. 1 0
      vendor/golang.org/x/sys/unix/ztypes_linux_arm.go
  39. 1 0
      vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go
  40. 1 0
      vendor/golang.org/x/sys/unix/ztypes_linux_mips.go
  41. 1 0
      vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go
  42. 1 0
      vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go
  43. 1 0
      vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go
  44. 1 0
      vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go
  45. 1 0
      vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go
  46. 1 0
      vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go

+ 5 - 5
Gopkg.lock

@@ -41,7 +41,7 @@
   branch = "master"
   name = "github.com/miniflux/miniflux-go"
   packages = ["."]
-  revision = "a2caa9187ebe4378f36c8e680825586a890154c9"
+  revision = "2efd82e81054cf01433e81c419a7c84e62e6a52c"
 
 [[projects]]
   name = "github.com/tdewolff/minify"
@@ -65,13 +65,13 @@
   branch = "master"
   name = "golang.org/x/crypto"
   packages = ["acme","acme/autocert","bcrypt","blowfish","ssh/terminal"]
-  revision = "9f005a07e0d31d45e6656d241bb5c0f2efd4bc94"
+  revision = "b080dc9a8c480b08e698fb1219160d598526310f"
 
 [[projects]]
   branch = "master"
   name = "golang.org/x/net"
   packages = ["context","context/ctxhttp","html","html/atom","html/charset"]
-  revision = "fb018015d54fd2e3bfd5362a041991d350fde9d7"
+  revision = "c7086645de248775cbf2373cf5ca4d2fa664b8c1"
 
 [[projects]]
   branch = "master"
@@ -83,7 +83,7 @@
   branch = "master"
   name = "golang.org/x/sys"
   packages = ["unix","windows"]
-  revision = "82aafbf43bf885069dc71b7e7c2f9d7a614d47da"
+  revision = "4ff8c001ce4cc464e644b922325097228fce14d8"
 
 [[projects]]
   branch = "master"
@@ -100,6 +100,6 @@
 [solve-meta]
   analyzer-name = "dep"
   analyzer-version = 1
-  inputs-digest = "ade513f4a86a1f49ce3508aa55f40cf2b1f172d6f3679649e48de67a82715431"
+  inputs-digest = "338222e5111416c46b2b8bde149443abc542b386dd02aff2a0dd6e13334bcf28"
   solver-name = "gps-cdcl"
   solver-version = 1

+ 4 - 0
Gopkg.toml

@@ -33,6 +33,10 @@
   branch = "master"
   name = "github.com/lib/pq"
 
+[[constraint]]
+  branch = "master"
+  name = "github.com/miniflux/miniflux-go"
+
 [[constraint]]
   name = "github.com/tdewolff/minify"
   version = "2.3.3"

+ 3 - 1
README.md

@@ -31,7 +31,9 @@ TODO
 - [ ] Gzip compression
 - [ ] Integration tests
 - [X] Flush history
-- [ ] OAuth2
+- [X] OAuth2
+- [ ] Bookmarks
+- [ ] Touch events
 
 Credits
 -------

+ 71 - 3
integration_test.go

@@ -495,15 +495,83 @@ func TestDiscoverSubscriptions(t *testing.T) {
 	}
 
 	if subscriptions[0].Title != "Feed" {
-		t.Fatalf(`Invalid userID, got "%v" instead of "%v"`, subscriptions[0].Title, "Feed")
+		t.Fatalf(`Invalid feed title, got "%v" instead of "%v"`, subscriptions[0].Title, "Feed")
 	}
 
 	if subscriptions[0].Type != "atom" {
-		t.Fatalf(`Invalid userID, got "%v" instead of "%v"`, subscriptions[0].Type, "atom")
+		t.Fatalf(`Invalid feed type, got "%v" instead of "%v"`, subscriptions[0].Type, "atom")
 	}
 
 	if subscriptions[0].URL != "https://miniflux.net/feed" {
-		t.Fatalf(`Invalid userID, got "%v" instead of "%v"`, subscriptions[0].URL, "https://miniflux.net/feed")
+		t.Fatalf(`Invalid feed URL, got "%v" instead of "%v"`, subscriptions[0].URL, "https://miniflux.net/feed")
+	}
+}
+
+func TestCreateFeed(t *testing.T) {
+	username := getRandomUsername()
+	client := miniflux.NewClient(testBaseURL, testAdminUsername, testAdminPassword)
+	_, err := client.CreateUser(username, testStandardPassword, false)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	client = miniflux.NewClient(testBaseURL, username, testStandardPassword)
+	categories, err := client.Categories()
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	feedID, err := client.CreateFeed("https://miniflux.net/feed", categories[0].ID)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	if feedID == 0 {
+		t.Fatalf(`Invalid feed ID, got "%v"`, feedID)
+	}
+}
+
+func TestCannotCreateDuplicatedFeed(t *testing.T) {
+	username := getRandomUsername()
+	client := miniflux.NewClient(testBaseURL, testAdminUsername, testAdminPassword)
+	_, err := client.CreateUser(username, testStandardPassword, false)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	client = miniflux.NewClient(testBaseURL, username, testStandardPassword)
+	categories, err := client.Categories()
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	feedID, err := client.CreateFeed("https://miniflux.net/feed", categories[0].ID)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	if feedID == 0 {
+		t.Fatalf(`Invalid feed ID, got "%v"`, feedID)
+	}
+
+	_, err = client.CreateFeed("https://miniflux.net/feed", categories[0].ID)
+	if err == nil {
+		t.Fatal(`Duplicated feeds should not be allowed`)
+	}
+}
+
+func TestCreateFeedWithInexistingCategory(t *testing.T) {
+	username := getRandomUsername()
+	client := miniflux.NewClient(testBaseURL, testAdminUsername, testAdminPassword)
+	_, err := client.CreateUser(username, testStandardPassword, false)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	client = miniflux.NewClient(testBaseURL, username, testStandardPassword)
+	_, err = client.CreateFeed("https://miniflux.net/feed", -1)
+	if err == nil {
+		t.Fatal(`Feeds should not be created with inexisting category`)
 	}
 }
 

+ 6 - 1
server/api/controller/feed.go

@@ -6,6 +6,7 @@ package api
 
 import (
 	"errors"
+
 	"github.com/miniflux/miniflux2/server/api/payload"
 	"github.com/miniflux/miniflux2/server/core"
 )
@@ -25,7 +26,11 @@ func (c *Controller) CreateFeed(ctx *core.Context, request *core.Request, respon
 		return
 	}
 
-	response.JSON().Created(feed)
+	type result struct {
+		FeedID int64 `json:"feed_id"`
+	}
+
+	response.JSON().Created(&result{FeedID: feed.ID})
 }
 
 // RefreshFeed is the API handler to refresh a feed.

+ 0 - 1
storage/feed.go

@@ -168,7 +168,6 @@ func (s *Storage) CreateFeed(feed *model.Feed) error {
 		feed.EtagHeader,
 		feed.LastModifiedHeader,
 	).Scan(&feed.ID)
-
 	if err != nil {
 		return fmt.Errorf("unable to create feed: %v", err)
 	}

+ 4 - 3
storage/icon.go

@@ -7,10 +7,11 @@ package storage
 import (
 	"database/sql"
 	"fmt"
-	"github.com/miniflux/miniflux2/helper"
-	"github.com/miniflux/miniflux2/model"
 	"strings"
 	"time"
+
+	"github.com/miniflux/miniflux2/helper"
+	"github.com/miniflux/miniflux2/model"
 )
 
 func (s *Storage) HasIcon(feedID int64) bool {
@@ -89,7 +90,7 @@ func (s *Storage) CreateFeedIcon(feed *model.Feed, icon *model.Icon) error {
 
 	_, err = s.db.Exec(`INSERT INTO feed_icons (feed_id, icon_id) VALUES ($1, $2)`, feed.ID, icon.ID)
 	if err != nil {
-		return fmt.Errorf("Unable to create feed icon: %v", err)
+		return fmt.Errorf("unable to create feed icon: %v", err)
 	}
 
 	return nil

+ 1 - 1
vendor/github.com/miniflux/miniflux-go/README.md

@@ -34,7 +34,7 @@ func main() {
     client := miniflux.NewClient("https://api.example.org", "admin", "secret")
 
     // Fetch all feeds.
-    feeds, err := userClient.Feeds()
+    feeds, err := client.Feeds()
     if err != nil {
         fmt.Println(err)
         return

+ 10 - 6
vendor/github.com/miniflux/miniflux-go/client.go

@@ -214,23 +214,27 @@ func (c *Client) Feed(feedID int64) (*Feed, error) {
 }
 
 // CreateFeed creates a new feed.
-func (c *Client) CreateFeed(url string, categoryID int64) (*Feed, error) {
+func (c *Client) CreateFeed(url string, categoryID int64) (int64, error) {
 	body, err := c.request.Post("/v1/feeds", map[string]interface{}{
 		"feed_url":    url,
 		"category_id": categoryID,
 	})
 	if err != nil {
-		return nil, err
+		return 0, err
 	}
 	defer body.Close()
 
-	var feed *Feed
+	type result struct {
+		FeedID int64 `json:"feed_id"`
+	}
+
+	var r result
 	decoder := json.NewDecoder(body)
-	if err := decoder.Decode(&feed); err != nil {
-		return nil, fmt.Errorf("miniflux: response error (%v)", err)
+	if err := decoder.Decode(&r); err != nil {
+		return 0, fmt.Errorf("miniflux: response error (%v)", err)
 	}
 
-	return feed, nil
+	return r.FeedID, nil
 }
 
 // UpdateFeed updates a feed.

+ 3 - 8
vendor/golang.org/x/crypto/ssh/terminal/util_windows.go

@@ -17,6 +17,8 @@
 package terminal
 
 import (
+	"os"
+
 	"golang.org/x/sys/windows"
 )
 
@@ -71,13 +73,6 @@ func GetSize(fd int) (width, height int, err error) {
 	return int(info.Size.X), int(info.Size.Y), nil
 }
 
-// passwordReader is an io.Reader that reads from a specific Windows HANDLE.
-type passwordReader int
-
-func (r passwordReader) Read(buf []byte) (int, error) {
-	return windows.Read(windows.Handle(r), buf)
-}
-
 // ReadPassword reads a line of input from a terminal without local echo.  This
 // is commonly used for inputting passwords and other sensitive data. The slice
 // returned does not include the \n.
@@ -98,5 +93,5 @@ func ReadPassword(fd int) ([]byte, error) {
 		windows.SetConsoleMode(windows.Handle(fd), old)
 	}()
 
-	return readPasswordLine(passwordReader(fd))
+	return readPasswordLine(os.NewFile(uintptr(fd), "stdin"))
 }

+ 7 - 0
vendor/golang.org/x/net/http/httpproxy/export_test.go

@@ -0,0 +1,7 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package httpproxy
+
+var ExportUseProxy = (*Config).useProxy

+ 239 - 0
vendor/golang.org/x/net/http/httpproxy/proxy.go

@@ -0,0 +1,239 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package httpproxy provides support for HTTP proxy determination
+// based on environment variables, as provided by net/http's
+// ProxyFromEnvironment function.
+//
+// The API is not subject to the Go 1 compatibility promise and may change at
+// any time.
+package httpproxy
+
+import (
+	"errors"
+	"fmt"
+	"net"
+	"net/url"
+	"os"
+	"strings"
+	"unicode/utf8"
+
+	"golang.org/x/net/idna"
+)
+
+// Config holds configuration for HTTP proxy settings. See
+// FromEnvironment for details.
+type Config struct {
+	// HTTPProxy represents the value of the HTTP_PROXY or
+	// http_proxy environment variable. It will be used as the proxy
+	// URL for HTTP requests and HTTPS requests unless overridden by
+	// HTTPSProxy or NoProxy.
+	HTTPProxy string
+
+	// HTTPSProxy represents the HTTPS_PROXY or https_proxy
+	// environment variable. It will be used as the proxy URL for
+	// HTTPS requests unless overridden by NoProxy.
+	HTTPSProxy string
+
+	// NoProxy represents the NO_PROXY or no_proxy environment
+	// variable. It specifies URLs that should be excluded from
+	// proxying as a comma-separated list of domain names or a
+	// single asterisk (*) to indicate that no proxying should be
+	// done. A domain name matches that name and all subdomains. A
+	// domain name with a leading "." matches subdomains only. For
+	// example "foo.com" matches "foo.com" and "bar.foo.com";
+	// ".y.com" matches "x.y.com" but not "y.com".
+	NoProxy string
+
+	// CGI holds whether the current process is running
+	// as a CGI handler (FromEnvironment infers this from the
+	// presence of a REQUEST_METHOD environment variable).
+	// When this is set, ProxyForURL will return an error
+	// when HTTPProxy applies, because a client could be
+	// setting HTTP_PROXY maliciously. See https://golang.org/s/cgihttpproxy.
+	CGI bool
+}
+
+// FromEnvironment returns a Config instance populated from the
+// environment variables HTTP_PROXY, HTTPS_PROXY and NO_PROXY (or the
+// lowercase versions thereof). HTTPS_PROXY takes precedence over
+// HTTP_PROXY for https requests.
+//
+// The environment values may be either a complete URL or a
+// "host[:port]", in which case the "http" scheme is assumed. An error
+// is returned if the value is a different form.
+func FromEnvironment() *Config {
+	return &Config{
+		HTTPProxy:  getEnvAny("HTTP_PROXY", "http_proxy"),
+		HTTPSProxy: getEnvAny("HTTPS_PROXY", "https_proxy"),
+		NoProxy:    getEnvAny("NO_PROXY", "no_proxy"),
+		CGI:        os.Getenv("REQUEST_METHOD") != "",
+	}
+}
+
+func getEnvAny(names ...string) string {
+	for _, n := range names {
+		if val := os.Getenv(n); val != "" {
+			return val
+		}
+	}
+	return ""
+}
+
+// ProxyFunc returns a function that determines the proxy URL to use for
+// a given request URL. Changing the contents of cfg will not affect
+// proxy functions created earlier.
+//
+// A nil URL and nil error are returned if no proxy is defined in the
+// environment, or a proxy should not be used for the given request, as
+// defined by NO_PROXY.
+//
+// As a special case, if req.URL.Host is "localhost" (with or without a
+// port number), then a nil URL and nil error will be returned.
+func (cfg *Config) ProxyFunc() func(reqURL *url.URL) (*url.URL, error) {
+	// Prevent Config changes from affecting the function calculation.
+	// TODO Preprocess proxy settings for more efficient evaluation.
+	cfg1 := *cfg
+	return cfg1.proxyForURL
+}
+
+func (cfg *Config) proxyForURL(reqURL *url.URL) (*url.URL, error) {
+	var proxy string
+	if reqURL.Scheme == "https" {
+		proxy = cfg.HTTPSProxy
+	}
+	if proxy == "" {
+		proxy = cfg.HTTPProxy
+		if proxy != "" && cfg.CGI {
+			return nil, errors.New("refusing to use HTTP_PROXY value in CGI environment; see golang.org/s/cgihttpproxy")
+		}
+	}
+	if proxy == "" {
+		return nil, nil
+	}
+	if !cfg.useProxy(canonicalAddr(reqURL)) {
+		return nil, nil
+	}
+	proxyURL, err := url.Parse(proxy)
+	if err != nil ||
+		(proxyURL.Scheme != "http" &&
+			proxyURL.Scheme != "https" &&
+			proxyURL.Scheme != "socks5") {
+		// proxy was bogus. Try prepending "http://" to it and
+		// see if that parses correctly. If not, we fall
+		// through and complain about the original one.
+		if proxyURL, err := url.Parse("http://" + proxy); err == nil {
+			return proxyURL, nil
+		}
+	}
+	if err != nil {
+		return nil, fmt.Errorf("invalid proxy address %q: %v", proxy, err)
+	}
+	return proxyURL, nil
+}
+
+// useProxy reports whether requests to addr should use a proxy,
+// according to the NO_PROXY or no_proxy environment variable.
+// addr is always a canonicalAddr with a host and port.
+func (cfg *Config) useProxy(addr string) bool {
+	if len(addr) == 0 {
+		return true
+	}
+	host, _, err := net.SplitHostPort(addr)
+	if err != nil {
+		return false
+	}
+	if host == "localhost" {
+		return false
+	}
+	if ip := net.ParseIP(host); ip != nil {
+		if ip.IsLoopback() {
+			return false
+		}
+	}
+
+	noProxy := cfg.NoProxy
+	if noProxy == "*" {
+		return false
+	}
+
+	addr = strings.ToLower(strings.TrimSpace(addr))
+	if hasPort(addr) {
+		addr = addr[:strings.LastIndex(addr, ":")]
+	}
+
+	for _, p := range strings.Split(noProxy, ",") {
+		p = strings.ToLower(strings.TrimSpace(p))
+		if len(p) == 0 {
+			continue
+		}
+		if hasPort(p) {
+			p = p[:strings.LastIndex(p, ":")]
+		}
+		if addr == p {
+			return false
+		}
+		if len(p) == 0 {
+			// There is no host part, likely the entry is malformed; ignore.
+			continue
+		}
+		if p[0] == '.' && (strings.HasSuffix(addr, p) || addr == p[1:]) {
+			// no_proxy ".foo.com" matches "bar.foo.com" or "foo.com"
+			return false
+		}
+		if p[0] != '.' && strings.HasSuffix(addr, p) && addr[len(addr)-len(p)-1] == '.' {
+			// no_proxy "foo.com" matches "bar.foo.com"
+			return false
+		}
+	}
+	return true
+}
+
+var portMap = map[string]string{
+	"http":   "80",
+	"https":  "443",
+	"socks5": "1080",
+}
+
+// canonicalAddr returns url.Host but always with a ":port" suffix
+func canonicalAddr(url *url.URL) string {
+	addr := url.Hostname()
+	if v, err := idnaASCII(addr); err == nil {
+		addr = v
+	}
+	port := url.Port()
+	if port == "" {
+		port = portMap[url.Scheme]
+	}
+	return net.JoinHostPort(addr, port)
+}
+
+// Given a string of the form "host", "host:port", or "[ipv6::address]:port",
+// return true if the string includes a port.
+func hasPort(s string) bool { return strings.LastIndex(s, ":") > strings.LastIndex(s, "]") }
+
+func idnaASCII(v string) (string, error) {
+	// TODO: Consider removing this check after verifying performance is okay.
+	// Right now punycode verification, length checks, context checks, and the
+	// permissible character tests are all omitted. It also prevents the ToASCII
+	// call from salvaging an invalid IDN, when possible. As a result it may be
+	// possible to have two IDNs that appear identical to the user where the
+	// ASCII-only version causes an error downstream whereas the non-ASCII
+	// version does not.
+	// Note that for correct ASCII IDNs ToASCII will only do considerably more
+	// work, but it will not cause an allocation.
+	if isASCII(v) {
+		return v, nil
+	}
+	return idna.Lookup.ToASCII(v)
+}
+
+func isASCII(s string) bool {
+	for i := 0; i < len(s); i++ {
+		if s[i] >= utf8.RuneSelf {
+			return false
+		}
+	}
+	return true
+}

+ 298 - 0
vendor/golang.org/x/net/http/httpproxy/proxy_test.go

@@ -0,0 +1,298 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package httpproxy_test
+
+import (
+	"bytes"
+	"errors"
+	"fmt"
+	"net/url"
+	"os"
+	"strings"
+	"testing"
+
+	"golang.org/x/net/http/httpproxy"
+)
+
+type proxyForURLTest struct {
+	cfg     httpproxy.Config
+	req     string // URL to fetch; blank means "http://example.com"
+	want    string
+	wanterr error
+}
+
+func (t proxyForURLTest) String() string {
+	var buf bytes.Buffer
+	space := func() {
+		if buf.Len() > 0 {
+			buf.WriteByte(' ')
+		}
+	}
+	if t.cfg.HTTPProxy != "" {
+		fmt.Fprintf(&buf, "http_proxy=%q", t.cfg.HTTPProxy)
+	}
+	if t.cfg.HTTPSProxy != "" {
+		space()
+		fmt.Fprintf(&buf, "https_proxy=%q", t.cfg.HTTPSProxy)
+	}
+	if t.cfg.NoProxy != "" {
+		space()
+		fmt.Fprintf(&buf, "no_proxy=%q", t.cfg.NoProxy)
+	}
+	req := "http://example.com"
+	if t.req != "" {
+		req = t.req
+	}
+	space()
+	fmt.Fprintf(&buf, "req=%q", req)
+	return strings.TrimSpace(buf.String())
+}
+
+var proxyForURLTests = []proxyForURLTest{{
+	cfg: httpproxy.Config{
+		HTTPProxy: "127.0.0.1:8080",
+	},
+	want: "http://127.0.0.1:8080",
+}, {
+	cfg: httpproxy.Config{
+		HTTPProxy: "cache.corp.example.com:1234",
+	},
+	want: "http://cache.corp.example.com:1234",
+}, {
+	cfg: httpproxy.Config{
+		HTTPProxy: "cache.corp.example.com",
+	},
+	want: "http://cache.corp.example.com",
+}, {
+	cfg: httpproxy.Config{
+		HTTPProxy: "https://cache.corp.example.com",
+	},
+	want: "https://cache.corp.example.com",
+}, {
+	cfg: httpproxy.Config{
+		HTTPProxy: "http://127.0.0.1:8080",
+	},
+	want: "http://127.0.0.1:8080",
+}, {
+	cfg: httpproxy.Config{
+		HTTPProxy: "https://127.0.0.1:8080",
+	},
+	want: "https://127.0.0.1:8080",
+}, {
+	cfg: httpproxy.Config{
+		HTTPProxy: "socks5://127.0.0.1",
+	},
+	want: "socks5://127.0.0.1",
+}, {
+	// Don't use secure for http
+	cfg: httpproxy.Config{
+		HTTPProxy:  "http.proxy.tld",
+		HTTPSProxy: "secure.proxy.tld",
+	},
+	req:  "http://insecure.tld/",
+	want: "http://http.proxy.tld",
+}, {
+	// Use secure for https.
+	cfg: httpproxy.Config{
+		HTTPProxy:  "http.proxy.tld",
+		HTTPSProxy: "secure.proxy.tld",
+	},
+	req:  "https://secure.tld/",
+	want: "http://secure.proxy.tld",
+}, {
+	cfg: httpproxy.Config{
+		HTTPProxy:  "http.proxy.tld",
+		HTTPSProxy: "https://secure.proxy.tld",
+	},
+	req:  "https://secure.tld/",
+	want: "https://secure.proxy.tld",
+}, {
+	// Issue 16405: don't use HTTP_PROXY in a CGI environment,
+	// where HTTP_PROXY can be attacker-controlled.
+	cfg: httpproxy.Config{
+		HTTPProxy: "http://10.1.2.3:8080",
+		CGI:       true,
+	},
+	want:    "<nil>",
+	wanterr: errors.New("refusing to use HTTP_PROXY value in CGI environment; see golang.org/s/cgihttpproxy"),
+}, {
+	// HTTPS proxy is still used even in CGI environment.
+	// (perhaps dubious but it's the historical behaviour).
+	cfg: httpproxy.Config{
+		HTTPSProxy: "https://secure.proxy.tld",
+		CGI:        true,
+	},
+	req:  "https://secure.tld/",
+	want: "https://secure.proxy.tld",
+}, {
+	want: "<nil>",
+}, {
+	cfg: httpproxy.Config{
+		NoProxy:   "example.com",
+		HTTPProxy: "proxy",
+	},
+	req:  "http://example.com/",
+	want: "<nil>",
+}, {
+	cfg: httpproxy.Config{
+		NoProxy:   ".example.com",
+		HTTPProxy: "proxy",
+	},
+	req:  "http://example.com/",
+	want: "<nil>",
+}, {
+	cfg: httpproxy.Config{
+		NoProxy:   "ample.com",
+		HTTPProxy: "proxy",
+	},
+	req:  "http://example.com/",
+	want: "http://proxy",
+}, {
+	cfg: httpproxy.Config{
+		NoProxy:   "example.com",
+		HTTPProxy: "proxy",
+	},
+	req:  "http://foo.example.com/",
+	want: "<nil>",
+}, {
+	cfg: httpproxy.Config{
+		NoProxy:   ".foo.com",
+		HTTPProxy: "proxy",
+	},
+	req:  "http://example.com/",
+	want: "http://proxy",
+}}
+
+func testProxyForURL(t *testing.T, tt proxyForURLTest) {
+	t.Helper()
+	reqURLStr := tt.req
+	if reqURLStr == "" {
+		reqURLStr = "http://example.com"
+	}
+	reqURL, err := url.Parse(reqURLStr)
+	if err != nil {
+		t.Errorf("invalid URL %q", reqURLStr)
+		return
+	}
+	cfg := tt.cfg
+	proxyForURL := cfg.ProxyFunc()
+	url, err := proxyForURL(reqURL)
+	if g, e := fmt.Sprintf("%v", err), fmt.Sprintf("%v", tt.wanterr); g != e {
+		t.Errorf("%v: got error = %q, want %q", tt, g, e)
+		return
+	}
+	if got := fmt.Sprintf("%s", url); got != tt.want {
+		t.Errorf("%v: got URL = %q, want %q", tt, url, tt.want)
+	}
+
+	// Check that changing the Config doesn't change the results
+	// of the functuon.
+	cfg = httpproxy.Config{}
+	url, err = proxyForURL(reqURL)
+	if g, e := fmt.Sprintf("%v", err), fmt.Sprintf("%v", tt.wanterr); g != e {
+		t.Errorf("(after mutating config) %v: got error = %q, want %q", tt, g, e)
+		return
+	}
+	if got := fmt.Sprintf("%s", url); got != tt.want {
+		t.Errorf("(after mutating config) %v: got URL = %q, want %q", tt, url, tt.want)
+	}
+}
+
+func TestProxyForURL(t *testing.T) {
+	for _, tt := range proxyForURLTests {
+		testProxyForURL(t, tt)
+	}
+}
+
+func TestFromEnvironment(t *testing.T) {
+	os.Setenv("HTTP_PROXY", "httpproxy")
+	os.Setenv("HTTPS_PROXY", "httpsproxy")
+	os.Setenv("NO_PROXY", "noproxy")
+	os.Setenv("REQUEST_METHOD", "")
+	got := httpproxy.FromEnvironment()
+	want := httpproxy.Config{
+		HTTPProxy:  "httpproxy",
+		HTTPSProxy: "httpsproxy",
+		NoProxy:    "noproxy",
+	}
+	if *got != want {
+		t.Errorf("unexpected proxy config, got %#v want %#v", got, want)
+	}
+}
+
+func TestFromEnvironmentWithRequestMethod(t *testing.T) {
+	os.Setenv("HTTP_PROXY", "httpproxy")
+	os.Setenv("HTTPS_PROXY", "httpsproxy")
+	os.Setenv("NO_PROXY", "noproxy")
+	os.Setenv("REQUEST_METHOD", "PUT")
+	got := httpproxy.FromEnvironment()
+	want := httpproxy.Config{
+		HTTPProxy:  "httpproxy",
+		HTTPSProxy: "httpsproxy",
+		NoProxy:    "noproxy",
+		CGI:        true,
+	}
+	if *got != want {
+		t.Errorf("unexpected proxy config, got %#v want %#v", got, want)
+	}
+}
+
+func TestFromEnvironmentLowerCase(t *testing.T) {
+	os.Setenv("http_proxy", "httpproxy")
+	os.Setenv("https_proxy", "httpsproxy")
+	os.Setenv("no_proxy", "noproxy")
+	os.Setenv("REQUEST_METHOD", "")
+	got := httpproxy.FromEnvironment()
+	want := httpproxy.Config{
+		HTTPProxy:  "httpproxy",
+		HTTPSProxy: "httpsproxy",
+		NoProxy:    "noproxy",
+	}
+	if *got != want {
+		t.Errorf("unexpected proxy config, got %#v want %#v", got, want)
+	}
+}
+
+var UseProxyTests = []struct {
+	host  string
+	match bool
+}{
+	// Never proxy localhost:
+	{"localhost", false},
+	{"127.0.0.1", false},
+	{"127.0.0.2", false},
+	{"[::1]", false},
+	{"[::2]", true}, // not a loopback address
+
+	{"barbaz.net", false},     // match as .barbaz.net
+	{"foobar.com", false},     // have a port but match
+	{"foofoobar.com", true},   // not match as a part of foobar.com
+	{"baz.com", true},         // not match as a part of barbaz.com
+	{"localhost.net", true},   // not match as suffix of address
+	{"local.localhost", true}, // not match as prefix as address
+	{"barbarbaz.net", true},   // not match because NO_PROXY have a '.'
+	{"www.foobar.com", false}, // match because NO_PROXY includes "foobar.com"
+}
+
+func TestUseProxy(t *testing.T) {
+	cfg := &httpproxy.Config{
+		NoProxy: "foobar.com, .barbaz.net",
+	}
+	for _, test := range UseProxyTests {
+		if httpproxy.ExportUseProxy(cfg, test.host+":80") != test.match {
+			t.Errorf("useProxy(%v) = %v, want %v", test.host, !test.match, test.match)
+		}
+	}
+}
+
+func TestInvalidNoProxy(t *testing.T) {
+	cfg := &httpproxy.Config{
+		NoProxy: ":1",
+	}
+	ok := httpproxy.ExportUseProxy(cfg, "example.com:80") // should not panic
+	if !ok {
+		t.Errorf("useProxy unexpected return; got false; want true")
+	}
+}

+ 1 - 0
vendor/golang.org/x/sys/unix/linux/types.go

@@ -512,6 +512,7 @@ type EpollEvent C.struct_my_epoll_event
 
 const (
 	AT_FDCWD            = C.AT_FDCWD
+	AT_NO_AUTOMOUNT     = C.AT_NO_AUTOMOUNT
 	AT_REMOVEDIR        = C.AT_REMOVEDIR
 	AT_SYMLINK_FOLLOW   = C.AT_SYMLINK_FOLLOW
 	AT_SYMLINK_NOFOLLOW = C.AT_SYMLINK_NOFOLLOW

+ 0 - 6
vendor/golang.org/x/sys/unix/mkall.sh

@@ -80,12 +80,6 @@ darwin_arm64)
 	mksysnum="./mksysnum_darwin.pl $(xcrun --show-sdk-path --sdk iphoneos)/usr/include/sys/syscall.h"
 	mktypes="GOARCH=$GOARCH go tool cgo -godefs"
 	;;
-dragonfly_386)
-	mkerrors="$mkerrors -m32"
-	mksyscall="./mksyscall.pl -l32 -dragonfly"
-	mksysnum="curl -s 'http://gitweb.dragonflybsd.org/dragonfly.git/blob_plain/HEAD:/sys/kern/syscalls.master' | ./mksysnum_dragonfly.pl"
-	mktypes="GOARCH=$GOARCH go tool cgo -godefs"
-	;;
 dragonfly_amd64)
 	mkerrors="$mkerrors -m64"
 	mksyscall="./mksyscall.pl -dragonfly"

+ 0 - 1
vendor/golang.org/x/sys/unix/syscall_linux.go

@@ -1410,7 +1410,6 @@ func Vmsplice(fd int, iovs []Iovec, flags int) (int, error) {
 // Msgget
 // Msgrcv
 // Msgsnd
-// Newfstatat
 // Nfsservctl
 // Personality
 // Pselect6

+ 1 - 0
vendor/golang.org/x/sys/unix/syscall_linux_386.go

@@ -54,6 +54,7 @@ func Pipe2(p []int, flags int) (err error) {
 //sys	Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64_64
 //sys	Fchown(fd int, uid int, gid int) (err error) = SYS_FCHOWN32
 //sys	Fstat(fd int, stat *Stat_t) (err error) = SYS_FSTAT64
+//sys	Fstatat(dirfd int, path string, stat *Stat_t, flags int) (err error) = SYS_FSTATAT64
 //sys	Ftruncate(fd int, length int64) (err error) = SYS_FTRUNCATE64
 //sysnb	Getegid() (egid int) = SYS_GETEGID32
 //sysnb	Geteuid() (euid int) = SYS_GETEUID32

+ 1 - 0
vendor/golang.org/x/sys/unix/syscall_linux_amd64.go

@@ -11,6 +11,7 @@ package unix
 //sys	Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64
 //sys	Fchown(fd int, uid int, gid int) (err error)
 //sys	Fstat(fd int, stat *Stat_t) (err error)
+//sys	Fstatat(dirfd int, path string, stat *Stat_t, flags int) (err error) = SYS_NEWFSTATAT
 //sys	Fstatfs(fd int, buf *Statfs_t) (err error)
 //sys	Ftruncate(fd int, length int64) (err error)
 //sysnb	Getegid() (egid int)

+ 1 - 0
vendor/golang.org/x/sys/unix/syscall_linux_arm.go

@@ -77,6 +77,7 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, err error) {
 //sys	Dup2(oldfd int, newfd int) (err error)
 //sys	Fchown(fd int, uid int, gid int) (err error) = SYS_FCHOWN32
 //sys	Fstat(fd int, stat *Stat_t) (err error) = SYS_FSTAT64
+//sys	Fstatat(dirfd int, path string, stat *Stat_t, flags int) (err error) = SYS_FSTATAT64
 //sysnb	Getegid() (egid int) = SYS_GETEGID32
 //sysnb	Geteuid() (euid int) = SYS_GETEUID32
 //sysnb	Getgid() (gid int) = SYS_GETGID32

+ 1 - 0
vendor/golang.org/x/sys/unix/syscall_linux_mips64x.go

@@ -10,6 +10,7 @@ package unix
 //sys	Dup2(oldfd int, newfd int) (err error)
 //sys	EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error)
 //sys	Fchown(fd int, uid int, gid int) (err error)
+//sys	Fstatat(dirfd int, path string, stat *Stat_t, flags int) (err error) = SYS_NEWFSTATAT
 //sys	Fstatfs(fd int, buf *Statfs_t) (err error)
 //sys	Ftruncate(fd int, length int64) (err error)
 //sysnb	Getegid() (egid int)

+ 1 - 0
vendor/golang.org/x/sys/unix/syscall_linux_mipsx.go

@@ -65,6 +65,7 @@ func Syscall9(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr,
 
 //sys	Lstat(path string, stat *Stat_t) (err error) = SYS_LSTAT64
 //sys	Fstat(fd int, stat *Stat_t) (err error) = SYS_FSTAT64
+//sys	Fstatat(dirfd int, path string, stat *Stat_t, flags int) (err error) = SYS_FSTATAT64
 //sys	Stat(path string, stat *Stat_t) (err error) = SYS_STAT64
 
 //sys	Utime(path string, buf *Utimbuf) (err error)

+ 1 - 0
vendor/golang.org/x/sys/unix/syscall_linux_ppc64x.go

@@ -11,6 +11,7 @@ package unix
 //sys	Dup2(oldfd int, newfd int) (err error)
 //sys	Fchown(fd int, uid int, gid int) (err error)
 //sys	Fstat(fd int, stat *Stat_t) (err error)
+//sys	Fstatat(dirfd int, path string, stat *Stat_t, flags int) (err error) = SYS_NEWFSTATAT
 //sys	Fstatfs(fd int, buf *Statfs_t) (err error)
 //sys	Ftruncate(fd int, length int64) (err error)
 //sysnb	Getegid() (egid int)

+ 1 - 0
vendor/golang.org/x/sys/unix/syscall_linux_s390x.go

@@ -15,6 +15,7 @@ import (
 //sys	Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64
 //sys	Fchown(fd int, uid int, gid int) (err error)
 //sys	Fstat(fd int, stat *Stat_t) (err error)
+//sys	Fstatat(dirfd int, path string, stat *Stat_t, flags int) (err error) = SYS_NEWFSTATAT
 //sys	Fstatfs(fd int, buf *Statfs_t) (err error)
 //sys	Ftruncate(fd int, length int64) (err error)
 //sysnb	Getegid() (egid int)

+ 1 - 0
vendor/golang.org/x/sys/unix/syscall_linux_sparc64.go

@@ -10,6 +10,7 @@ package unix
 //sys	Dup2(oldfd int, newfd int) (err error)
 //sys	Fchown(fd int, uid int, gid int) (err error)
 //sys	Fstat(fd int, stat *Stat_t) (err error)
+//sys	Fstatat(dirfd int, path string, stat *Stat_t, flags int) (err error) = SYS_FSTATAT64
 //sys	Fstatfs(fd int, buf *Statfs_t) (err error)
 //sys	Ftruncate(fd int, length int64) (err error)
 //sysnb	Getegid() (egid int)

+ 38 - 0
vendor/golang.org/x/sys/unix/syscall_linux_test.go

@@ -195,6 +195,44 @@ func TestUname(t *testing.T) {
 	t.Logf("OS: %s/%s %s", string(utsname.Sysname[:]), string(utsname.Machine[:]), string(utsname.Release[:]))
 }
 
+func TestFstatat(t *testing.T) {
+	defer chtmpdir(t)()
+
+	touch(t, "file1")
+
+	var st1 unix.Stat_t
+	err := unix.Stat("file1", &st1)
+	if err != nil {
+		t.Fatalf("Stat: %v", err)
+	}
+
+	var st2 unix.Stat_t
+	err = unix.Fstatat(unix.AT_FDCWD, "file1", &st2, 0)
+	if err != nil {
+		t.Fatalf("Fstatat: %v", err)
+	}
+
+	if st1 != st2 {
+		t.Errorf("Fstatat: returned stat does not match Stat")
+	}
+
+	os.Symlink("file1", "symlink1")
+
+	err = unix.Lstat("symlink1", &st1)
+	if err != nil {
+		t.Fatalf("Lstat: %v", err)
+	}
+
+	err = unix.Fstatat(unix.AT_FDCWD, "symlink1", &st2, unix.AT_SYMLINK_NOFOLLOW)
+	if err != nil {
+		t.Fatalf("Fstatat: %v", err)
+	}
+
+	if st1 != st2 {
+		t.Errorf("Fstatat: returned stat does not match Lstat")
+	}
+}
+
 // utilities taken from os/os_test.go
 
 func touch(t *testing.T, name string) {

+ 15 - 0
vendor/golang.org/x/sys/unix/zsyscall_linux_386.go

@@ -1569,6 +1569,21 @@ func Fstat(fd int, stat *Stat_t) (err error) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
+func Fstatat(dirfd int, path string, stat *Stat_t, flags int) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall6(SYS_FSTATAT64, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), uintptr(flags), 0, 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
 func Ftruncate(fd int, length int64) (err error) {
 	_, _, e1 := Syscall(SYS_FTRUNCATE64, uintptr(fd), uintptr(length), uintptr(length>>32))
 	if e1 != 0 {

+ 15 - 0
vendor/golang.org/x/sys/unix/zsyscall_linux_amd64.go

@@ -1566,6 +1566,21 @@ func Fstat(fd int, stat *Stat_t) (err error) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
+func Fstatat(dirfd int, path string, stat *Stat_t, flags int) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall6(SYS_NEWFSTATAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), uintptr(flags), 0, 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
 func Fstatfs(fd int, buf *Statfs_t) (err error) {
 	_, _, e1 := Syscall(SYS_FSTATFS, uintptr(fd), uintptr(unsafe.Pointer(buf)), 0)
 	if e1 != 0 {

+ 15 - 0
vendor/golang.org/x/sys/unix/zsyscall_linux_arm.go

@@ -1728,6 +1728,21 @@ func Fstat(fd int, stat *Stat_t) (err error) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
+func Fstatat(dirfd int, path string, stat *Stat_t, flags int) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall6(SYS_FSTATAT64, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), uintptr(flags), 0, 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
 func Getegid() (egid int) {
 	r0, _, _ := RawSyscall(SYS_GETEGID32, 0, 0, 0)
 	egid = int(r0)

+ 15 - 0
vendor/golang.org/x/sys/unix/zsyscall_linux_mips.go

@@ -2014,6 +2014,21 @@ func Fstat(fd int, stat *Stat_t) (err error) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
+func Fstatat(dirfd int, path string, stat *Stat_t, flags int) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall6(SYS_FSTATAT64, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), uintptr(flags), 0, 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
 func Stat(path string, stat *Stat_t) (err error) {
 	var _p0 *byte
 	_p0, err = BytePtrFromString(path)

+ 15 - 0
vendor/golang.org/x/sys/unix/zsyscall_linux_mips64.go

@@ -1546,6 +1546,21 @@ func Fchown(fd int, uid int, gid int) (err error) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
+func Fstatat(dirfd int, path string, stat *Stat_t, flags int) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall6(SYS_NEWFSTATAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), uintptr(flags), 0, 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
 func Fstatfs(fd int, buf *Statfs_t) (err error) {
 	_, _, e1 := Syscall(SYS_FSTATFS, uintptr(fd), uintptr(unsafe.Pointer(buf)), 0)
 	if e1 != 0 {

+ 15 - 0
vendor/golang.org/x/sys/unix/zsyscall_linux_mips64le.go

@@ -1546,6 +1546,21 @@ func Fchown(fd int, uid int, gid int) (err error) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
+func Fstatat(dirfd int, path string, stat *Stat_t, flags int) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall6(SYS_NEWFSTATAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), uintptr(flags), 0, 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
 func Fstatfs(fd int, buf *Statfs_t) (err error) {
 	_, _, e1 := Syscall(SYS_FSTATFS, uintptr(fd), uintptr(unsafe.Pointer(buf)), 0)
 	if e1 != 0 {

+ 15 - 0
vendor/golang.org/x/sys/unix/zsyscall_linux_mipsle.go

@@ -2014,6 +2014,21 @@ func Fstat(fd int, stat *Stat_t) (err error) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
+func Fstatat(dirfd int, path string, stat *Stat_t, flags int) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall6(SYS_FSTATAT64, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), uintptr(flags), 0, 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
 func Stat(path string, stat *Stat_t) (err error) {
 	var _p0 *byte
 	_p0, err = BytePtrFromString(path)

+ 15 - 0
vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64.go

@@ -1556,6 +1556,21 @@ func Fstat(fd int, stat *Stat_t) (err error) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
+func Fstatat(dirfd int, path string, stat *Stat_t, flags int) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall6(SYS_NEWFSTATAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), uintptr(flags), 0, 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
 func Fstatfs(fd int, buf *Statfs_t) (err error) {
 	_, _, e1 := Syscall(SYS_FSTATFS, uintptr(fd), uintptr(unsafe.Pointer(buf)), 0)
 	if e1 != 0 {

+ 15 - 0
vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64le.go

@@ -1556,6 +1556,21 @@ func Fstat(fd int, stat *Stat_t) (err error) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
+func Fstatat(dirfd int, path string, stat *Stat_t, flags int) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall6(SYS_NEWFSTATAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), uintptr(flags), 0, 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
 func Fstatfs(fd int, buf *Statfs_t) (err error) {
 	_, _, e1 := Syscall(SYS_FSTATFS, uintptr(fd), uintptr(unsafe.Pointer(buf)), 0)
 	if e1 != 0 {

+ 15 - 0
vendor/golang.org/x/sys/unix/zsyscall_linux_s390x.go

@@ -1566,6 +1566,21 @@ func Fstat(fd int, stat *Stat_t) (err error) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
+func Fstatat(dirfd int, path string, stat *Stat_t, flags int) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall6(SYS_NEWFSTATAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), uintptr(flags), 0, 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
 func Fstatfs(fd int, buf *Statfs_t) (err error) {
 	_, _, e1 := Syscall(SYS_FSTATFS, uintptr(fd), uintptr(unsafe.Pointer(buf)), 0)
 	if e1 != 0 {

+ 1 - 0
vendor/golang.org/x/sys/unix/ztypes_linux_386.go

@@ -644,6 +644,7 @@ type EpollEvent struct {
 
 const (
 	AT_FDCWD            = -0x64
+	AT_NO_AUTOMOUNT     = 0x800
 	AT_REMOVEDIR        = 0x200
 	AT_SYMLINK_FOLLOW   = 0x400
 	AT_SYMLINK_NOFOLLOW = 0x100

+ 1 - 0
vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go

@@ -662,6 +662,7 @@ type EpollEvent struct {
 
 const (
 	AT_FDCWD            = -0x64
+	AT_NO_AUTOMOUNT     = 0x800
 	AT_REMOVEDIR        = 0x200
 	AT_SYMLINK_FOLLOW   = 0x400
 	AT_SYMLINK_NOFOLLOW = 0x100

+ 1 - 0
vendor/golang.org/x/sys/unix/ztypes_linux_arm.go

@@ -633,6 +633,7 @@ type EpollEvent struct {
 
 const (
 	AT_FDCWD            = -0x64
+	AT_NO_AUTOMOUNT     = 0x800
 	AT_REMOVEDIR        = 0x200
 	AT_SYMLINK_FOLLOW   = 0x400
 	AT_SYMLINK_NOFOLLOW = 0x100

+ 1 - 0
vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go

@@ -641,6 +641,7 @@ type EpollEvent struct {
 
 const (
 	AT_FDCWD            = -0x64
+	AT_NO_AUTOMOUNT     = 0x800
 	AT_REMOVEDIR        = 0x200
 	AT_SYMLINK_FOLLOW   = 0x400
 	AT_SYMLINK_NOFOLLOW = 0x100

+ 1 - 0
vendor/golang.org/x/sys/unix/ztypes_linux_mips.go

@@ -638,6 +638,7 @@ type EpollEvent struct {
 
 const (
 	AT_FDCWD            = -0x64
+	AT_NO_AUTOMOUNT     = 0x800
 	AT_REMOVEDIR        = 0x200
 	AT_SYMLINK_FOLLOW   = 0x400
 	AT_SYMLINK_NOFOLLOW = 0x100

+ 1 - 0
vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go

@@ -643,6 +643,7 @@ type EpollEvent struct {
 
 const (
 	AT_FDCWD            = -0x64
+	AT_NO_AUTOMOUNT     = 0x800
 	AT_REMOVEDIR        = 0x200
 	AT_SYMLINK_FOLLOW   = 0x400
 	AT_SYMLINK_NOFOLLOW = 0x100

+ 1 - 0
vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go

@@ -643,6 +643,7 @@ type EpollEvent struct {
 
 const (
 	AT_FDCWD            = -0x64
+	AT_NO_AUTOMOUNT     = 0x800
 	AT_REMOVEDIR        = 0x200
 	AT_SYMLINK_FOLLOW   = 0x400
 	AT_SYMLINK_NOFOLLOW = 0x100

+ 1 - 0
vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go

@@ -638,6 +638,7 @@ type EpollEvent struct {
 
 const (
 	AT_FDCWD            = -0x64
+	AT_NO_AUTOMOUNT     = 0x800
 	AT_REMOVEDIR        = 0x200
 	AT_SYMLINK_FOLLOW   = 0x400
 	AT_SYMLINK_NOFOLLOW = 0x100

+ 1 - 0
vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go

@@ -651,6 +651,7 @@ type EpollEvent struct {
 
 const (
 	AT_FDCWD            = -0x64
+	AT_NO_AUTOMOUNT     = 0x800
 	AT_REMOVEDIR        = 0x200
 	AT_SYMLINK_FOLLOW   = 0x400
 	AT_SYMLINK_NOFOLLOW = 0x100

+ 1 - 0
vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go

@@ -651,6 +651,7 @@ type EpollEvent struct {
 
 const (
 	AT_FDCWD            = -0x64
+	AT_NO_AUTOMOUNT     = 0x800
 	AT_REMOVEDIR        = 0x200
 	AT_SYMLINK_FOLLOW   = 0x400
 	AT_SYMLINK_NOFOLLOW = 0x100

+ 1 - 0
vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go

@@ -668,6 +668,7 @@ type EpollEvent struct {
 
 const (
 	AT_FDCWD            = -0x64
+	AT_NO_AUTOMOUNT     = 0x800
 	AT_REMOVEDIR        = 0x200
 	AT_SYMLINK_FOLLOW   = 0x400
 	AT_SYMLINK_NOFOLLOW = 0x100